﻿#include "fhmainwindow.h"
#include "ui_fhmainwindow.h"
#define CONFIGPATH (QCoreApplication::applicationDirPath() + "fsconfig.ini") //设置一个用于存储的ini文件
QString globalFHDirPath;
QString m_lastUsedPath;

FHMainWindow::FHMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::FHMainWindow)
{
    ui->setupUi(this);
    this->setCentralWidget(ui->fhcentralwidget);
    //this->setCentralWidget(ui->fhtabWidget);
    //    this->setLayout(ui->fhgridLayout);

    // 数据库连接
    // 不使用指针
    fhDatabase = QSqlDatabase::addDatabase("QMYSQL", "myUniqueConnectionName");//创建数据库对象

    // 读取配置文件中的IP地址
    QSettings Isetting(CONFIGPATH, QSettings::IniFormat);
    Isetting.setIniCodec(QTextCodec::codecForName("UTF-8"));
    QString configIP = Isetting.value("settings/ip").toString().trimmed();

    QString finalIP = "127.0.0.1"; // 默认IP
    bool useConfigIP = false;

    // 如果配置文件中有IP地址，尝试连接
    if (!configIP.isEmpty()) {
        // 简单的IP地址格式验证
        QRegularExpression ipRegex("^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
        if (ipRegex.match(configIP).hasMatch()) {
            // 创建临时数据库连接测试配置的IP
            QSqlDatabase testDB = QSqlDatabase::addDatabase("QMYSQL", "testConnection");
            testDB.setHostName(configIP);
            testDB.setPort(3306);
            testDB.setDatabaseName("yrsy");
            testDB.setUserName("root");
            testDB.setPassword("123456");
            testDB.setConnectOptions("MYSQL_CHARSET=utf8mb4");

            if (testDB.open()) {
                finalIP = configIP;
                useConfigIP = true;
                testDB.close();
                QMessageBox::information(this, "数据库连接", QString("成功连接到配置的IP: %1").arg(configIP));
            } else {
                qWarning() << "配置的IP连接失败:" << configIP << "- 错误:" << testDB.lastError().text();
            }

            // 移除临时测试连接
            QSqlDatabase::removeDatabase("testConnection");
        } else {
            qWarning() << "配置的IP格式无效:" << configIP;
        }
    }

    fhDatabase.setHostName(finalIP); //为本机的 IP
    fhDatabase.setPort(3306); //端口号，一般数据库都为 3306
    fhDatabase.setDatabaseName("fhkl"); //自己设的数据库名
    fhDatabase.setUserName("root"); //登录用户名 在创建数据库时设置的用户名和密码
    fhDatabase.setPassword("123456"); //登录密码
    fhDatabase.setConnectOptions("MYSQL_CHARSET=utf8mb4"); // 设置连接字符集为 utf8mb4
    qDebug() << "使用数据库IP:" << finalIP;

    if(!fhDatabase.open())
    {
        QMessageBox::warning(this,"打开MySQL数据库失败",fhDatabase.lastError().text());
    }
    else
    {
        qDebug() << "打开MySQL数据库成功，使用IP:" << finalIP;
        if (useConfigIP) {
            // 如果使用了配置的IP，可以在这里添加额外的提示或日志
        }
    }

    // 检查数据库是否存在这些表，没有就创建
    checkAndCreateFhklTable(&fhDatabase);// 传递对象的引用
    checkAndCreateSampleTable(&fhDatabase);
    checkAndCreateExperimentTable(&fhDatabase);

    //准备数据模型
    fhkl_model = new QStandardItemModel();
    sample_model = new QStandardItemModel();
    experiment_model = new QStandardItemModel();

    // 权限检测
    if (login::userType == "User") {
        // 获取menuBar的指针
        QMenuBar *menuBar = this->menuBar();

        // 假设menu_Import是QMenu的实例，并且你有一个指向它的指针
        QMenu *menuImport = this->findChild<QMenu*>("menu_Import");
        QMenu *menuHandle = this->findChild<QMenu*>("menu_Handle");
        QMenu *menuMaintain = this->findChild<QMenu*>("menu_Maintain");
        QMenu *menuSetting = this->findChild<QMenu*>("menu_setting");

        if (menuImport) {
            // 获取menuImport的QAction，通常QMenu的QAction是其自己
            QAction *importAction = menuImport->menuAction();

            // 从menuBar中移除该QAction，这将移除整个QMenu
            menuBar->removeAction(importAction);
        }
        if (menuHandle) {
            // 获取menuImport的QAction，通常QMenu的QAction是其自己
            QAction *handleAction = menuHandle->menuAction();

            // 从menuBar中移除该QAction，这将移除整个QMenu
            menuBar->removeAction(handleAction);
        }
        if (menuMaintain) {
            // 获取menuImport的QAction，通常QMenu的QAction是其自己
            QAction *maintainAction = menuMaintain->menuAction();

            // 从menuBar中移除该QAction，这将移除整个QMenu
            menuBar->removeAction(maintainAction);
        }
        if (menuSetting) {
            // 获取menuSetting的QAction，通常QMenu的QAction是其自己
            QAction *settingAction = menuSetting->menuAction();

            // 从menuBar中移除该QAction，这将移除整个QMenu
            menuBar->removeAction(settingAction);
        }
        ui->deleteselected_btn->setVisible(false);
    }

    // 控制全选勾选框初始隐藏
    ui->selectall_checkBox->hide();

    // 连接信号和槽
    connect(ui->selectall_checkBox, &QCheckBox::stateChanged, this, &FHMainWindow::onSelectAllCheckBoxStateChanged);
    connect(ui->fhtabWidget, &QTabWidget::currentChanged, this, [this]() {

        //ui->selectall_checkBox->setCheckState(Qt::Unchecked);  // 设置为未选中状态

        int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引

        QStandardItemModel *model = nullptr;

        if (currentIndex == 0) {
            model = dynamic_cast<QStandardItemModel*>(ui->fhkl_tableView->model());
        } else if (currentIndex == 1) {
            model = dynamic_cast<QStandardItemModel*>(ui->sample_tableView->model());
        } else if (currentIndex == 2) {
            model = dynamic_cast<QStandardItemModel*>(ui->syxx_tableView->model());
        }

        if (!model) {
            ui->selectedcount_label->setText("");
            return;
        } else {
            ui->selectall_checkBox->setCheckState((update_selected_count() == model->rowCount()) ? Qt::Checked : Qt::Unchecked);  // 设置为未选中状态
        }

        if(model->headerData(0, Qt::Horizontal).toString() != "选择") {
            ui->selectall_checkBox->hide();
        } else {
            ui->selectall_checkBox->show();
        }

        update_model_count();
        update_selected_count();

        //ui->selectedcount_label->setText("");
    });
    connect(ui->takeselected_btn, &QPushButton::clicked, this, &FHMainWindow::onTakeSelectedBtnClicked);

    QTimer::singleShot(0, this, [=]() {
        on_fhkl_search_btn3_clicked();
        on_sample_search_btn3_clicked();
        on_syxx_search_btn3_clicked();
    });

    QSettings setting(CONFIGPATH, QSettings::IniFormat); // 打开存放登录信息的ini文件
    setting.setIniCodec(QTextCodec::codecForName("UTF-8")); // 设置编码格式

    // 读取全局变量 fs 的文件夹路径
    globalFHDirPath = setting.value("fhsettings/fhdirpath").toString();
    qDebug() << "读取的文件夹路径:" << globalFHDirPath;

    // 检查是否存在 UTF-8 转义字符（如 \xE7 等），并尝试修正
    if (globalFHDirPath.contains("\\u")) {
        // 转换类似 \xE7 的转义字符为实际中文
        QByteArray rawBytes = QByteArray::fromPercentEncoding(globalFHDirPath.toUtf8());
        globalFHDirPath = QString::fromUtf8(rawBytes);

        // 更新配置文件中的值为修正后的路径
        setting.setValue("settings/fsdirpath", globalFHDirPath);
        qDebug() << "修正后的文件夹路径:" << globalFHDirPath;
    }

    if (globalFHDirPath.isEmpty()) {
        if (login::userType != "User"){
            QMessageBox::information(this, tr("文件夹路径为空"), tr("请配置文件夹路径！"));
        }
    }
}

FHMainWindow::~FHMainWindow()
{
    // 移除数据库连接
    fhDatabase.close(); // 关闭数据库连接
    QSqlDatabase::removeDatabase(fhDatabase.connectionName()); // 移除数据库连接
    delete ui;
}

void FHMainWindow::showFhklInTableView(FlyFireParticle *particle) {

    // 清除model已有的数据
    if (fhkl_model) {
        fhkl_model->clear();
        delete fhkl_model; // 删除旧的model实例以避免内存泄漏
        fhkl_model = nullptr;
    }

    // 获取飞火颗粒总表表头
    QStringList headers = getFlyFireParticleHeaders();

    //准备数据模型
    fhkl_model = new QStandardItemModel();

    // 插入表头到model
    int i = 0;
    foreach (const QString &header, headers) {
        fhkl_model->setHorizontalHeaderItem(i, new QStandardItem(header));
        ++i;
    }

    //设置选中时为整行选中
    ui->fhkl_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);

    //设置表格的单元为只读属性，即不能编辑
    ui->fhkl_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);

    //如果你用在QTableView中使用右键菜单，需启用该属性
    ui->fhkl_tableView->setContextMenuPolicy(Qt::CustomContextMenu);

    int fhkl_row = 0;
    int fhkl_column = 0;
    foreach (const QString &header, headers) {
        QString itemText;
        switch (fhkl_column) {
        case 0: // 飞火颗粒编号
            itemText = particle->particle_id;
            break;
        case 1: // 飞火颗粒材料名称
            itemText = particle->material_name;
            break;
        case 2: // 飞火颗粒材料种类
            itemText = particle->material_type;
            break;
        case 3: // 燃烧前飞火颗粒质量(g)
            itemText = QString::number(particle->pre_burn_weight);
            break;
        case 4: // 燃烧前飞火颗粒尺寸(mm)
            itemText = particle->diameter_length;
            break;
        case 5: // 飞火颗粒加工方法
            itemText = particle->processing_method;
            break;
        case 6: // 燃烧后飞火颗粒质量(g)
            itemText = QString::number(particle->post_burn_weight);
            break;
        case 7: // 燃烧后飞火颗粒尺寸(mm)
            itemText = particle->post_burn_diameter_length;
            break;
        case 8: // 飞火颗粒数目（个）
            itemText = QString::number(particle->particle_count);
            break;
        case 9: // 飞火颗粒来源或产地
            itemText = particle->origin;
            break;
        case 10: // 飞火颗粒图片
            itemText = particle->image_path;
            break;
        default:
            itemText = "";
            break;
        }
        // 设置单元格数据
        fhkl_model->setItem(fhkl_row, fhkl_column, new QStandardItem(itemText));
        ++fhkl_column;
    }

    ui->fhkl_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);


    //利用setModel()方法将数据模型与QTableView绑定
    ui->fhkl_tableView->setModel(fhkl_model);

    // 手动调整列宽
    ui->fhkl_tableView->resize(ui->fhkl_tableView->width(), ui->fhkl_tableView->height()); // 重新调整表格尺寸

    // 设置字体
    ui->fhkl_tableView->setFont(QFont("SimSun", 10));

    // 使用QDesktopServices::openUrl来打开文件
    //QProcess::startDetached("explorer " + particle->image_path);
    // 传入文件（照片）绝对路径，使用默认方式打开
    /*QString path = particle->image_path;
    qDebug() << path;
    QFileInfo fileInfo(path);
    if (!fileInfo.exists()) {
        qWarning() << "文件不存在:" << path;
        //return;
    }
    // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
    QUrl fileUrl = QUrl::fromLocalFile(path);//应当放出来，fhkl表提供了假地址，代码暂时无效
    //QUrl fileUrl = QUrl::fromLocalFile("F:\\CUIT\\xfsjk\\试验V3\\实验台图片\\实验台.jpg");
    qDebug() << fileUrl;
    // 使用 QDesktopServices::openUrl 来打开文件
    if (!QDesktopServices::openUrl(fileUrl)) {
        qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
    }*/

}

// 检查并创建飞火颗粒表
bool FHMainWindow::checkAndCreateFhklTable(QSqlDatabase *fhDatabase) {
    if (!fhDatabase || !fhDatabase->isOpen()) {
        qWarning() << "数据库连接无效或未打开";
        return false;
    }

    try {
        // 检查表是否存在
        QSqlQuery checkTable(*fhDatabase);
        if (!checkTable.exec("SHOW TABLES LIKE 'fhkl_total'")) {
            qWarning() << "SHOW TABLES LIKE 查询失败: " << checkTable.lastError().text();
            return false;
        }

        if (!checkTable.next()) {
            // 表不存在，创建表
            QSqlQuery createTable(*fhDatabase);
            QString createTableSQL = R"(
                                     CREATE TABLE `fhkl_total` (
                                     `id` INT NOT NULL AUTO_INCREMENT,
                                     `particle_id` VARCHAR(20) NOT NULL,
                                     `material_name` VARCHAR(255) NOT NULL,
                                     `material_type` VARCHAR(255) NOT NULL,
                                     `pre_burn_weight` DOUBLE NOT NULL,
                                     `diameter_length` VARCHAR(255) NOT NULL,
                                     `processing_method` VARCHAR(255) NOT NULL,
                                     `post_burn_weight` DOUBLE NOT NULL,
                                     `post_burn_diameter_length` VARCHAR(255) NOT NULL,
                                     `particle_count` INT NOT NULL,
                                     `origin` VARCHAR(255) NOT NULL,
                                     `image_path` VARCHAR(255),
                                     `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                     `updated_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                                     PRIMARY KEY (`id`)
                                     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
                                     )";

            if (!createTable.exec(createTableSQL)) {
                QMessageBox::critical(nullptr, "错误", "创建表失败: " + createTable.lastError().text());
                return false;
            } else {
                QMessageBox::warning(nullptr, "表已创建", "表 'fhkl_total' 已成功创建。");
                return true;
            }
        }
        return true; // 表已存在
    } catch (const std::exception &e) {
        qCritical() << "在 checkAndCreateTable 中发生异常: " << e.what();
        return false;
    } catch (...) {
        qCritical() << "在 checkAndCreateTable 中发生未知异常";
        return false;
    }
}

// 检查并创建试样信息表
bool FHMainWindow::checkAndCreateSampleTable(QSqlDatabase *sampleDatabase) {
    if (!sampleDatabase || !sampleDatabase->isOpen()) {
        qWarning() << "数据库连接无效或未打开";
        return false;
    }

    try {
        // 检查表是否存在
        QSqlQuery checkTable(*sampleDatabase);
        if (!checkTable.exec("SHOW TABLES LIKE 'sample_total'")) {
            qWarning() << "SHOW TABLES LIKE 查询失败: " << checkTable.lastError().text();
            return false;
        }

        if (!checkTable.next()) {
            // 表不存在，创建表
            QSqlQuery createTable(*sampleDatabase);
            QString createTableSQL = R"(
                                     CREATE TABLE `sample_total` (
                                     `id` INT NOT NULL AUTO_INCREMENT,
                                     `sample_id` VARCHAR(20) NOT NULL,
                                     `sample_name` VARCHAR(255) NOT NULL,
                                     `sample_type` VARCHAR(255) NOT NULL,
                                     `sample_weight` DOUBLE NOT NULL,
                                     `sample_dimensions` VARCHAR(255) NOT NULL,
                                     `sample_thickness` INT NOT NULL,
                                     `sample_water_content` VARCHAR(20) NOT NULL,
                                     `sample_service_life` VARCHAR(255) NOT NULL,
                                     `sample_origin` VARCHAR(255) NOT NULL,
                                     `sample_image_path` VARCHAR(255),
                                     `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                     `updated_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                                     PRIMARY KEY (`id`)
                                     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
                                     )";

            if (!createTable.exec(createTableSQL)) {
                QMessageBox::critical(nullptr, "错误", "创建表失败: " + createTable.lastError().text());
                return false;
            } else {
                QMessageBox::warning(nullptr, "表已创建", "表 'sample_total' 已成功创建。");
                return true;
            }
        }
        return true; // 表已存在
    } catch (const std::exception &e) {
        qCritical() << "在 checkAndCreateSampleTable 中发生异常: " << e.what();
        return false;
    } catch (...) {
        qCritical() << "在 checkAndCreateSampleTable 中发生未知异常";
        return false;
    }
}

// 检查并创建试验及结果信息表
bool FHMainWindow::checkAndCreateExperimentTable(QSqlDatabase *experimentDatabase) {
    if (!experimentDatabase || !experimentDatabase->isOpen()) {
        qWarning() << "数据库连接无效或未打开";
        return false;
    }

    try {
        // 检查表是否存在
        QSqlQuery checkTable(*experimentDatabase);
        if (!checkTable.exec("SHOW TABLES LIKE 'experiment_total'")) {
            qWarning() << "SHOW TABLES LIKE 查询失败: " << checkTable.lastError().text();
            return false;
        }

        if (!checkTable.next()) {
            // 表不存在，创建表
            QSqlQuery createTable(*experimentDatabase);
            QString createTableSQL = R"(
                                     CREATE TABLE `experiment_total` (
                                     `id` INT NOT NULL AUTO_INCREMENT,
                                     `test_id` VARCHAR(20) NOT NULL,
                                     `test_time` VARCHAR(255) NOT NULL,
                                     `ignition_method` VARCHAR(255) NOT NULL,
                                     `sample_id` VARCHAR(20) NOT NULL,
                                     `particle_id` VARCHAR(20) NOT NULL,
                                     `sample_name` VARCHAR(255) NOT NULL,
                                     `fire_particle` VARCHAR(255) NOT NULL,
                                     `particle_count` INT NOT NULL,
                                     `test_wind_speed` VARCHAR(20) NOT NULL,
                                     `ignition_duration` VARCHAR(255) NOT NULL,
                                     `hazard_level` VARCHAR(255),
                                     `image_path` VARCHAR(255),
                                     `created_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
                                     `updated_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
                                     PRIMARY KEY (`id`)
                                     ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
                                     )";

            if (!createTable.exec(createTableSQL)) {
                QMessageBox::critical(nullptr, "错误", "创建表失败: " + createTable.lastError().text());
                return false;
            } else {
                QMessageBox::warning(nullptr, "表已创建", "表 'experiment_total' 已成功创建。");
                return true;
            }
        }
        return true; // 表已存在
    } catch (const std::exception &e) {
        qCritical() << "在 checkAndCreateExperimentTable 中发生异常: " << e.what();
        return false;
    } catch (...) {
        qCritical() << "在 checkAndCreateExperimentTable 中发生未知异常";
        return false;
    }
}

// 插入飞火颗粒结构体数据到fhkl_total表
bool FHMainWindow::insertParticleIntoDatabase(FlyFireParticle *particle, QSqlDatabase *database) {
    // 检查数据库连接是否有效
    if (!(*database).isOpen()) {
        qWarning() << "数据库连接不可用。";
        return false;
    }

    QSqlQuery query(*database);

    // 检查 particle_id 是否已存在
    query.prepare("SELECT COUNT(*) FROM `fhkl_total` WHERE `particle_id` = ?");
    query.addBindValue(particle->particle_id);

    if (!query.exec()) {
        qDebug() << "Failed to check for duplicate particle_id:" << query.lastError().text();
        return false;
    }

    // 判断结果集，如果记录数大于 0 则存在重复
    if (query.next() && query.value(0).toInt() > 0) {
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "数据重复",
                    QString("数据库中已存在相同的 particle_id: %1，是否覆盖插入？").arg(particle->particle_id),
                    QMessageBox::Yes | QMessageBox::No);

        if (reply == QMessageBox::No) {
            // 用户选择不覆盖，返回 false
            return false;
        } else {
            // 用户选择覆盖，继续后续的插入逻辑
            // 用户选择覆盖，删除已有的记录
            QSqlQuery deleteQuery(*database);
            deleteQuery.prepare("DELETE FROM `fhkl_total` WHERE `particle_id` = ?");
            deleteQuery.addBindValue(particle->particle_id);

            if (!deleteQuery.exec()) {
                qDebug() << "Failed to delete existing particle_id:" << deleteQuery.lastError().text();
                return false;
            }
        }
    }

    // 准备插入数据的SQL语句
    QString sql = R"(
                  INSERT INTO `fhkl_total` (
                  `particle_id`, `material_name`, `material_type`, `pre_burn_weight`,
                  `diameter_length`, `processing_method`, `post_burn_weight`,
                  `post_burn_diameter_length`, `particle_count`, `origin`, `image_path`,
                  `created_time`, `updated_time`
                  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
                  )";

    // 绑定参数到SQL语句
    query.prepare(sql);
    query.addBindValue(particle->particle_id);
    query.addBindValue(particle->material_name);
    query.addBindValue(particle->material_type);
    query.addBindValue(particle->pre_burn_weight);
    query.addBindValue(particle->diameter_length);
    query.addBindValue(particle->processing_method);
    query.addBindValue(particle->post_burn_weight);
    query.addBindValue(particle->post_burn_diameter_length);
    query.addBindValue(particle->particle_count);
    query.addBindValue(particle->origin);
    query.addBindValue(particle->image_path);

    // 执行插入操作
    if (!query.exec()) {
        qDebug() << "Failed to insert particle into database:" << query.lastError().text();
        return false;
    }

    return true;
}

// 插入试样信息结构体数据到sample_total表
bool FHMainWindow::insertSampleIntoDatabase(SampleInfo *sample, QSqlDatabase *database) {
    // 检查数据库连接是否有效
    if (!(*database).isOpen()) {
        qWarning() << "数据库连接不可用。";
        return false;
    }

    QSqlQuery query(*database);

    // 检查 sample_id 是否已存在
    query.prepare("SELECT COUNT(*) FROM `sample_total` WHERE `sample_id` = ?");
    query.addBindValue(sample->sample_id);

    if (!query.exec()) {
        qDebug() << "Failed to check for duplicate sample_id:" << query.lastError().text();
        return false;
    }

    // 判断结果集，如果记录数大于 0 则存在重复
    if (query.next() && query.value(0).toInt() > 0) {
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "数据重复",
                    QString("数据库中已存在相同的 sample_id: %1，是否覆盖插入？").arg(sample->sample_id),
                    QMessageBox::Yes | QMessageBox::No);

        if (reply == QMessageBox::No) {
            // 用户选择不覆盖，返回 false
            return false;
        } else {
            // 用户选择覆盖，继续后续的插入逻辑
            // 用户选择覆盖，删除已有的记录
            QSqlQuery deleteQuery(*database);
            deleteQuery.prepare("DELETE FROM `sample_total` WHERE `sample_id` = ?");
            deleteQuery.addBindValue(sample->sample_id);

            if (!deleteQuery.exec()) {
                qDebug() << "Failed to delete existing sample_id:" << deleteQuery.lastError().text();
                return false;
            }
        }
    }

    // 准备插入数据的SQL语句
    QString sql = R"(
                  INSERT INTO `sample_total` (
                  `sample_id`, `sample_name`, `sample_type`, `sample_weight`,
                  `sample_dimensions`, `sample_thickness`, `sample_water_content`,
                  `sample_service_life`, `sample_origin`, `sample_image_path`,
                  `created_time`, `updated_time`
                  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
                  )";

    // 绑定参数到SQL语句
    query.prepare(sql);
    query.addBindValue(sample->sample_id);
    query.addBindValue(sample->sample_name);
    query.addBindValue(sample->sample_type);
    query.addBindValue(sample->sample_weight);
    query.addBindValue(sample->sample_dimensions);
    query.addBindValue(sample->sample_thickness);
    query.addBindValue(sample->sample_water_content);
    query.addBindValue(sample->sample_service_life);
    query.addBindValue(sample->sample_origin);
    query.addBindValue(sample->sample_image_path);

    // 执行插入操作
    if (!query.exec()) {
        qDebug() << "Failed to insert sample into database:" << query.lastError().text();
        return false;
    }

    return true;
}

// 插入试验信息结构体数据到experiment_total表
bool FHMainWindow::insertExperimentIntoDatabase(ExperimentInfo *experiment, QSqlDatabase *database) {
    // 检查数据库连接是否有效
    if (!(*database).isOpen()) {
        qWarning() << "数据库连接不可用。";
        return false;
    }

    QSqlQuery query(*database);

    // 检查 test_id 是否已存在
    query.prepare("SELECT COUNT(*) FROM `experiment_total` WHERE `test_id` = ?");
    query.addBindValue(experiment->test_id);

    if (!query.exec()) {
        qDebug() << "Failed to check for duplicate test_id:" << query.lastError().text();
        return false;
    }

    // 判断结果集，如果记录数大于 0 则存在重复
    if (query.next() && query.value(0).toInt() > 0) {
        QMessageBox::StandardButton reply;
        reply = QMessageBox::question(this, "数据重复",
                    QString("数据库中已存在相同的 test_id: %1，是否覆盖插入？").arg(experiment->test_id),
                    QMessageBox::Yes | QMessageBox::No);

        if (reply == QMessageBox::No) {
            // 用户选择不覆盖，返回 false
            return false;
        } else {
            // 用户选择覆盖，继续后续的插入逻辑
            // 用户选择覆盖，删除已有的记录
            QSqlQuery deleteQuery(*database);
            deleteQuery.prepare("DELETE FROM `experiment_total` WHERE `test_id` = ?");
            deleteQuery.addBindValue(experiment->test_id);

            if (!deleteQuery.exec()) {
                qDebug() << "Failed to delete existing test_id:" << deleteQuery.lastError().text();
                return false;
            }
        }
    }

    // 准备插入数据的SQL语句
    QString sql = R"(
                  INSERT INTO `experiment_total` (
                  `test_id`, `test_time`, `ignition_method`, `sample_id`,
                  `particle_id`, `sample_name`, `fire_particle`, `particle_count`,
                  `test_wind_speed`, `ignition_duration`, `hazard_level`, `image_path`,
                  `created_time`, `updated_time`
                  ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(), NOW())
                  )";

    // 绑定参数到SQL语句
    query.prepare(sql);
    query.addBindValue(experiment->test_id);
    query.addBindValue(experiment->test_time);
    query.addBindValue(experiment->ignition_method);
    query.addBindValue(experiment->sample_id);
    query.addBindValue(experiment->particle_id);
    query.addBindValue(experiment->sample_name);
    query.addBindValue(experiment->fire_particle);
    query.addBindValue(experiment->particle_count);
    query.addBindValue(experiment->test_wind_speed);
    query.addBindValue(experiment->ignition_duration);
    query.addBindValue(experiment->hazard_level);
    query.addBindValue(experiment->image_path);

    // 执行插入操作
    if (!query.exec()) {
        qDebug() << "Failed to insert experiment into database:" << query.lastError().text();
        return false;
    }

    return true;
}

// 显示fhkl_total表所有数据
void FHMainWindow::showAllFhklInTableView(QSqlDatabase *database) {
    // 清除model已有的数据
    if (fhkl_model) {
        fhkl_model->clear();
        delete fhkl_model; // 删除旧的model实例以避免内存泄漏
        fhkl_model = nullptr;
    }

    // 设置表头header
    QStringList headers = getFlyFireParticleHeaders();

    // 准备model的数据
    fhkl_model = new QStandardItemModel();

    // 插入headers到model
    int i = 0;
    foreach (const QString &header, headers) {
        fhkl_model->setHorizontalHeaderItem(i, new QStandardItem(header));
        ++i;
    }

    // 设置tableview属性
    ui->fhkl_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->fhkl_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->fhkl_tableView->setContextMenuPolicy(Qt::CustomContextMenu);

    // 数据库 >> struct
    QSqlQuery query(*database);
    //query.prepare("SELECT * FROM `fhkl_total`");
    // 查询数据库，并按 particle_id 数字部分升序排序
    query.prepare("SELECT * FROM `fhkl_total` ORDER BY CAST(SUBSTRING(`particle_id`, 3) AS UNSIGNED) ASC");

    if (!query.exec()) {
        qWarning() << "Failed to fetch data from database:" << query.lastError().text();
        return;
    }

    // Fill model with data from the database
    int row = 0;
    while (query.next()) {
        // Create a new FlyFireParticle structure for each row
        FlyFireParticle particle;
        particle.particle_id = query.value("particle_id").toString();
        particle.material_name = query.value("material_name").toString();
        particle.material_type = query.value("material_type").toString();
        particle.pre_burn_weight = query.value("pre_burn_weight").toDouble();
        particle.diameter_length = query.value("diameter_length").toString();
        particle.processing_method = query.value("processing_method").toString();
        particle.post_burn_weight = query.value("post_burn_weight").toDouble();
        particle.post_burn_diameter_length = query.value("post_burn_diameter_length").toString();
        particle.particle_count = query.value("particle_count").toInt();
        particle.origin = query.value("origin").toString();
        //particle.image_path = query.value("image_path").toString();
        particle.image_path = dealImagePath(query.value("image_path").toString());

        // struct >> model
        int column = 0;
        fhkl_model->setItem(row, column++, new QStandardItem(particle.particle_id));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.material_name));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.material_type));
        fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.pre_burn_weight)));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.diameter_length));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.processing_method));
        fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.post_burn_weight)));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.post_burn_diameter_length));
        fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.particle_count)));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.origin));
        fhkl_model->setItem(row, column++, new QStandardItem(particle.image_path));

        row++;
    }

    // Adjust column size and bind the model to the QTableView
    ui->fhkl_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->fhkl_tableView->setModel(fhkl_model);

    // Resize the table view
    ui->fhkl_tableView->resize(ui->fhkl_tableView->width(), ui->fhkl_tableView->height());
    ui->fhkl_tableView->setFont(QFont("SimSun", 10));

    update_model_count();

}

// 显示sample_total表所有数据
void FHMainWindow::showAllSampleInTableView(QSqlDatabase *database) {
    // 清除model已有的数据
    if (sample_model) {
        sample_model->clear();
        delete sample_model; // 删除旧的model实例以避免内存泄漏
        sample_model = nullptr;
    }

    // 设置表头header
    QStringList headers = getSampleInfoHeaders();

    // 准备model的数据
    sample_model = new QStandardItemModel();

    // 插入headers到model
    int i = 0;
    foreach (const QString &header, headers) {
        sample_model->setHorizontalHeaderItem(i, new QStandardItem(header));
        ++i;
    }

    // 设置tableview属性
    ui->sample_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->sample_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->sample_tableView->setContextMenuPolicy(Qt::CustomContextMenu);

    // 数据库 >> struct
    QSqlQuery query(*database);
    //query.prepare("SELECT * FROM `sample_total`");
    // 查询数据库，并按 sample_id 数字部分升序排序
    query.prepare("SELECT * FROM `sample_total` ORDER BY CAST(SUBSTRING(`sample_id`, 2) AS UNSIGNED) ASC");

    if (!query.exec()) {
        qWarning() << "Failed to fetch data from database:" << query.lastError().text();
        return;
    }

    // Fill model with data from the database
    int row = 0;
    while (query.next()) {
        // Create a new SampleInfo structure for each row
        SampleInfo sample;
        sample.sample_id = query.value("sample_id").toString();
        sample.sample_name = query.value("sample_name").toString();
        sample.sample_type = query.value("sample_type").toString();
        sample.sample_weight = query.value("sample_weight").toDouble();
        sample.sample_dimensions = query.value("sample_dimensions").toString();
        sample.sample_thickness = query.value("sample_thickness").toInt();
        sample.sample_water_content = query.value("sample_water_content").toString();
        sample.sample_service_life = query.value("sample_service_life").toString();
        sample.sample_origin = query.value("sample_origin").toString();
        //sample.sample_image_path = query.value("sample_image_path").toString();
        sample.sample_image_path = dealImagePath(query.value("sample_image_path").toString());

        // struct >> model
        int column = 0;
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_id));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_name));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_type));
        sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_weight)));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_dimensions));
        sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_thickness)));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_water_content));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_service_life));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_origin));
        sample_model->setItem(row, column++, new QStandardItem(sample.sample_image_path));

        row++;
    }

    // Adjust column size and bind the model to the QTableView
    ui->sample_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->sample_tableView->setModel(sample_model);

    // Resize the table view
    ui->sample_tableView->resize(ui->sample_tableView->width(), ui->sample_tableView->height());
    ui->sample_tableView->setFont(QFont("SimSun", 10));

    update_model_count();
}

// 显示experiment_total表所有数据
void FHMainWindow::showAllExperimentInTableView(QSqlDatabase *database) {
    // 清除model已有的数据
    if (experiment_model) {
        experiment_model->clear();
        delete experiment_model; // 删除旧的model实例以避免内存泄漏
        experiment_model = nullptr;
    }

    // 设置表头header
    QStringList headers = getExperimentInfoHeaders();

    // 准备model的数据
    experiment_model = new QStandardItemModel();

    // 插入headers到model
    int i = 0;
    foreach (const QString &header, headers) {
        experiment_model->setHorizontalHeaderItem(i, new QStandardItem(header));
        ++i;
    }

    // 设置tableview属性
    ui->syxx_tableView->setSelectionBehavior(QAbstractItemView::SelectRows);
    ui->syxx_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
    ui->syxx_tableView->setContextMenuPolicy(Qt::CustomContextMenu);

    // 数据库 >> struct
    QSqlQuery query(*database);
    //query.prepare("SELECT * FROM `experiment_total`");
    // 查询数据库，并按 test_id 数字部分升序排序
    query.prepare("SELECT * FROM `experiment_total` ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC");

    if (!query.exec()) {
        qWarning() << "Failed to fetch data from database:" << query.lastError().text();
        return;
    }

    // Fill model with data from the database
    int row = 0;
    while (query.next()) {
        // Create a new ExperimentInfo structure for each row
        ExperimentInfo experiment;
        experiment.test_id = query.value("test_id").toString();
        experiment.test_time = query.value("test_time").toString();
        experiment.ignition_method = query.value("ignition_method").toString();
        experiment.sample_id = query.value("sample_id").toString();
        experiment.particle_id = query.value("particle_id").toString();
        experiment.sample_name = query.value("sample_name").toString();
        experiment.fire_particle = query.value("fire_particle").toString();
        experiment.particle_count = query.value("particle_count").toInt();
        experiment.test_wind_speed = query.value("test_wind_speed").toString();
        experiment.ignition_duration = query.value("ignition_duration").toString();
        experiment.hazard_level = query.value("hazard_level").toString();
        //experiment.image_path = query.value("image_path").toString();
        experiment.image_path = dealImagePath(query.value("image_path").toString());

        // struct >> model
        int column = 0;
        experiment_model->setItem(row, column++, new QStandardItem(experiment.test_id));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.test_time));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_method));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_id));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.particle_id));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_name));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.fire_particle));
        experiment_model->setItem(row, column++, new QStandardItem(QString::number(experiment.particle_count)));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.test_wind_speed));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_duration));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.hazard_level));
        experiment_model->setItem(row, column++, new QStandardItem(experiment.image_path));

        row++;
    }

    // Adjust column size and bind the model to the QTableView
    ui->syxx_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
    ui->syxx_tableView->setModel(experiment_model);

    // Resize the table view
    ui->syxx_tableView->resize(ui->sample_tableView->width(), ui->sample_tableView->height());
    ui->syxx_tableView->setFont(QFont("SimSun", 10));

    update_model_count();
}


// 导入飞火颗粒csv的槽函数
void FHMainWindow::on_action_fhkl_triggered()
{
    QString initialPath;
    if (m_lastUsedPath.isEmpty()) {
        // 第一次使用，默认桌面路径
        initialPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    } else {
        // 使用上一次的路径
        initialPath = m_lastUsedPath;
    }

    // 打开选择文件窗口
    QString filePath = QFileDialog::getOpenFileName(this, tr("打开飞火颗粒的CSV文件"), initialPath, tr("Excel Files (*.xlsx *.xls *.csv)"));

    // 保存这次使用的路径
    if (!filePath.isEmpty()) {
        m_lastUsedPath = QFileInfo(filePath).path(); // 只保存目录路径，不保存文件名
    }

    if(!filePath.contains("飞火颗粒基本信息表")) {
        qWarning() << "文件:" << filePath << "并不是飞火颗粒基本信息表！";
        QMessageBox::warning(this,"导入失败","文件:" + filePath + "并不是飞火颗粒基本信息表！");
        return ;
    }

    // 将csv数据赋值到结构体
    fhkl_struct = importCSV(filePath);

    // 调用插入函数，结构体 》 数据库
    if (insertParticleIntoDatabase(&fhkl_struct, &fhDatabase)) {
        qDebug() << "数据成功插入数据库。";
        QMessageBox::information(this, "成功", "数据成功插入数据库！");
    } else {
        qDebug() << "插入数据失败。";
        QMessageBox::warning(this, "失败", "数据插入失败，请检查选定的文件" + filePath);
    }

    // 显示在 TableView 中
    //showFhklInTableView(&fhkl_struct);
    showAllFhklInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// 导入试样信息csv的槽函数
void FHMainWindow::on_action_sample_triggered()
{   
    QString initialPath;
    if (m_lastUsedPath.isEmpty()) {
        // 第一次使用，默认桌面路径
        initialPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    } else {
        // 使用上一次的路径
        initialPath = m_lastUsedPath;
    }

    // 打开选择文件窗口
    QString filePath = QFileDialog::getOpenFileName(this, tr("打开试样基本信息的CSV文件"), initialPath, tr("Excel Files (*.xlsx *.xls *.csv)"));

    // 保存这次使用的路径
    if (!filePath.isEmpty()) {
        m_lastUsedPath = QFileInfo(filePath).path(); // 只保存目录路径，不保存文件名
    }

    if(!filePath.contains("试样基本信息表")) {
        qWarning() << "文件:" << filePath << "并不是试样基本信息表！";
        QMessageBox::warning(this,"导入失败","文件:" + filePath + "并不是试样基本信息表！");
        return ;
    }

    // 将csv数据赋值到结构体
    sample_struct = importSampleCsv(filePath);

    // 调用插入函数，结构体 》 数据库
    if (insertSampleIntoDatabase(&sample_struct, &fhDatabase)) {
        qDebug() << "数据成功插入数据库。";
        QMessageBox::information(this, "成功", "数据成功插入数据库！");
    } else {
        qDebug() << "插入数据失败。";
        QMessageBox::warning(this, "失败", "数据插入失败，请检查选定的文件" + filePath);
    }

    // 显示在 TableView 中
    showAllSampleInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// 导入试验及结果信息csv的槽函数
void FHMainWindow::on_action_syxx_triggered()
{
    QString initialPath;
    if (m_lastUsedPath.isEmpty()) {
        // 第一次使用，默认桌面路径
        initialPath = QStandardPaths::writableLocation(QStandardPaths::DesktopLocation);
    } else {
        // 使用上一次的路径
        initialPath = m_lastUsedPath;
    }

    // 打开选择文件窗口
    QString filePath = QFileDialog::getOpenFileName(this, tr("打开试验结果及基本信息表的CSV文件"), initialPath, tr("Excel Files (*.xlsx *.xls *.csv)"));

    // 保存这次使用的路径
    if (!filePath.isEmpty()) {
        m_lastUsedPath = QFileInfo(filePath).path(); // 只保存目录路径，不保存文件名
    }

    if(!filePath.contains("试验结果及基本信息表")) {
        qWarning() << "文件:" << filePath << "并不是试验结果及基本信息表！";
        QMessageBox::warning(this,"导入失败","文件:" + filePath + "并不是试验结果及基本信息表！");
        return ;
    }

    // 将csv数据赋值到结构体
    experiment_struct = importExperimentCsv(filePath);

    // 调用插入函数，结构体 》 数据库
    if (insertExperimentIntoDatabase(&experiment_struct, &fhDatabase)) {
        qDebug() << "数据成功插入数据库。";
        QMessageBox::information(this, "成功", "数据成功插入数据库！");
    } else {
        qDebug() << "插入数据失败。";
        QMessageBox::warning(this, "失败", "数据插入失败，请检查选定的文件" + filePath);
    }

    // 显示在 TableView 中
    showAllExperimentInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// 手工导入飞火颗粒槽函数
void FHMainWindow::on_action_insert_fhkl_triggered()
{
    //this->close();
    importbyhand *handInputDialog = new importbyhand(fhDatabase, 0); // 传递数据库对象
    handInputDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    handInputDialog->setWindowIcon(QIcon(":/images/fire.png"));
    handInputDialog->setWindowTitle("插入对话框");
    handInputDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    handInputDialog->show();
}

// 手工导入试样槽函数
void FHMainWindow::on_action_insert_sample_triggered()
{
    //this->close();
    importbyhand *handInputDialog = new importbyhand(fhDatabase, 1); // 传递数据库对象
    handInputDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    handInputDialog->setWindowIcon(QIcon(":/images/fire.png"));
    handInputDialog->setWindowTitle("插入对话框");
    handInputDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    handInputDialog->show();
}

// 手工导入试验及结果槽函数
void FHMainWindow::on_action_insert_syxx_triggered()
{
    //this->close();
    importbyhand *handInputDialog = new importbyhand(fhDatabase, 2); // 传递数据库对象
    handInputDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    handInputDialog->setWindowIcon(QIcon(":/images/fire.png"));
    handInputDialog->setWindowTitle("插入对话框");
    handInputDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    handInputDialog->show();
}

// 显示fhkl_total表所有数据，槽函数
void FHMainWindow::on_fhkl_search_btn3_clicked()
{
    showAllFhklInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// 显示sample_total表所有数据，槽函数
void FHMainWindow::on_sample_search_btn3_clicked()
{
    showAllSampleInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// 显示experiment_total表所有数据，槽函数
void FHMainWindow::on_syxx_search_btn3_clicked()
{
    showAllExperimentInTableView(&fhDatabase);
    ui->selectall_checkBox->hide();
    ui->selectedcount_label->setText("");
}

// fhkl_total表，基本查询，槽函数
void FHMainWindow::on_fhkl_search_btn1_clicked() {   
    // 如果对话框已经存在，则不创建新的，直接显示
    if (fhklSearchDialog) {
        fhklSearchDialog->raise();   // 将窗口置于最前
        fhklSearchDialog->activateWindow(); // 激活窗口
        return;
    }

    fhklSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    fhklSearchDialog->setLayout(formLayout);

    QList<QPair<QString, QString>> nameList({
                                                {"按飞火颗粒编号", "particle_id"},
                                                {"按飞火颗粒材料名称", "material_name"},
                                                {"按飞火颗粒材料种类", "material_type"},
                                                {"按飞火颗粒数目（个）", "particle_count"}
                                            });

    // 创建单选按钮组
    QRadioButton *particleIdRadioButton = new QRadioButton(nameList[0].first);
    QRadioButton *materialNameRadioButton = new QRadioButton(nameList[1].first);
    QRadioButton *materialTypeRadioButton = new QRadioButton(nameList[2].first);
    QRadioButton *particleCountRadioButton = new QRadioButton(nameList[3].first);

    // 设置单选按钮组
    QButtonGroup *searchGroup = new QButtonGroup();
    searchGroup->addButton(particleIdRadioButton);
    searchGroup->addButton(materialNameRadioButton);
    searchGroup->addButton(materialTypeRadioButton);
    searchGroup->addButton(particleCountRadioButton);
    searchGroup->setExclusive(true); // 确保只有一个按钮被选中
    // 设置第一个按钮为选中状态
    particleIdRadioButton->setChecked(true);

    // 创建输入框
    QLineEdit *searchLineEdit = new QLineEdit();

    // 添加单选按钮和输入框到表单布局
    formLayout->addRow(particleIdRadioButton);
    formLayout->addRow(materialNameRadioButton);
    formLayout->addRow(materialTypeRadioButton);
    formLayout->addRow(particleCountRadioButton);
    formLayout->addRow("请键入对应关键字：", searchLineEdit);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：仅可单选一项。");
    formLayout->addRow(noticeLabel);

    // 连接确认按钮的点击信号
    connect(confirmButton, &QPushButton::clicked, [=]() {
        QString searchKeyword = searchLineEdit->text();
        QString searchColumn;

        for (const QPair<QString, QString>& pair : nameList) {
            if (pair.first == searchGroup->checkedButton()->text().trimmed()) {
                searchColumn = pair.second;
                break;
            }
        }

        if (searchKeyword.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入搜索关键字。");
            return;
        }

        QString sqlQuery;
        QSqlQuery query(fhDatabase);
        sqlQuery = "SELECT * FROM `fhkl_total` WHERE " + searchColumn + " LIKE ? ORDER BY CAST(SUBSTRING(`particle_id`, 3) AS UNSIGNED) ASC";
        query.prepare(sqlQuery);
        query.addBindValue("%" + searchKeyword + "%"); // 使用通配符进行模糊匹配
        sqlQuery = QString("SELECT * FROM `fhkl_total` WHERE " + searchColumn + " LIKE %1 ORDER BY CAST(SUBSTRING(`particle_id`, 3) AS UNSIGNED) ASC").arg("%" + searchKeyword + "%");

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << sqlQuery << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        qDebug() << sqlQuery;

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

        // 清除原有数据
        if (fhkl_model) {
            fhkl_model->clear();
            delete fhkl_model;
            fhkl_model = nullptr;
        }

        // 准备model的数据
        fhkl_model = new QStandardItemModel();

        // 设置表头header
        QStringList headers = getFlyFireParticleHeaders();
        headers.prepend("选择"); // 在表头前加上一个"选择"列
        fhkl_model->setHorizontalHeaderLabels(headers);

        // Fill model with data from the database
        int row = 0;
        while (query.next()) {
            // 创建每行的第一列为勾选框
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true); // 设置为可勾选
            checkItem->setCheckState(Qt::Unchecked); // 默认未勾选

            fhkl_model->setItem(row, 0, checkItem); // 将勾选框设置到第一列

            // Create a new FlyFireParticle structure for each row
            FlyFireParticle particle;
            particle.particle_id = query.value("particle_id").toString();
            particle.material_name = query.value("material_name").toString();
            particle.material_type = query.value("material_type").toString();
            particle.pre_burn_weight = query.value("pre_burn_weight").toDouble();
            particle.diameter_length = query.value("diameter_length").toString();
            particle.processing_method = query.value("processing_method").toString();
            particle.post_burn_weight = query.value("post_burn_weight").toDouble();
            particle.post_burn_diameter_length = query.value("post_burn_diameter_length").toString();
            particle.particle_count = query.value("particle_count").toInt();
            particle.origin = query.value("origin").toString();
//            particle.image_path = query.value("image_path").toString();
            particle.image_path = dealImagePath(query.value("image_path").toString());
            // struct >> model
            int column = 1; // 从第二列开始
            fhkl_model->setItem(row, column++, new QStandardItem(particle.particle_id));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.material_name));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.material_type));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.pre_burn_weight)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.diameter_length));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.processing_method));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.post_burn_weight)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.post_burn_diameter_length));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.particle_count)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.origin));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.image_path));

            row++;
        }

        // Adjust column size and bind the model to the QTableView
        ui->fhkl_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->fhkl_tableView->setModel(fhkl_model);

        // Resize the table view
        ui->fhkl_tableView->resize(ui->fhkl_tableView->width(), ui->fhkl_tableView->height());
        ui->fhkl_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(fhkl_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < fhkl_model->columnCount(); ++col) {
                    QStandardItem* dataItem = fhkl_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == fhkl_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == fhkl_model->rowCount()";
                } else {
                    disconnect(ui->selectall_checkBox, &QCheckBox::stateChanged, this, &FHMainWindow::onSelectAllCheckBoxStateChanged);
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                    connect(ui->selectall_checkBox, &QCheckBox::stateChanged, this, &FHMainWindow::onSelectAllCheckBoxStateChanged);
                }
            }           
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        fhklSearchDialog->close();
    });

    // 连接destroyed信号，确保窗口关闭时将fhklSearchDialog置为nullptr
    connect(fhklSearchDialog, &QWidget::destroyed, this, [=]() {
        fhklSearchDialog = nullptr;
    });

    fhkl_Menu();

    fhklSearchDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    fhklSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    fhklSearchDialog->setFixedSize(500, 230);  // 设置窗口固定大小，宽度足够显示标题
    fhklSearchDialog->setWindowTitle("飞火颗粒基本信息总表-基本查询对话框");
    //fhklSearchDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
    //fhklSearchDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    fhklSearchDialog->show();
}

// sample_total表，基本查询，槽函数
void FHMainWindow::on_sample_search_btn1_clicked() {
    // 如果对话框已经存在，则不创建新的，直接显示
    if (sampleSearchDialog) {
        sampleSearchDialog->raise();   // 将窗口置于最前
        sampleSearchDialog->activateWindow(); // 激活窗口
        return;
    }

    sampleSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    sampleSearchDialog->setLayout(formLayout);

    QList<QPair<QString, QString>> nameList({
                                                {"按试样编号", "sample_id"},
                                                {"按试样材料名称", "sample_name"},
                                                {"按试样材料类型", "sample_type"}
                                            });

    // 创建单选按钮组
    QRadioButton *sampleIdRadioButton = new QRadioButton(nameList[0].first);
    QRadioButton *sampleNameRadioButton = new QRadioButton(nameList[1].first);
    QRadioButton *sampleTypeRadioButton = new QRadioButton(nameList[2].first);

    // 设置单选按钮组
    QButtonGroup *searchGroup = new QButtonGroup();
    searchGroup->addButton(sampleIdRadioButton);
    searchGroup->addButton(sampleNameRadioButton);
    searchGroup->addButton(sampleTypeRadioButton);
    searchGroup->setExclusive(true); // 确保只有一个按钮被选中
    // 设置第一个按钮为选中状态
    sampleIdRadioButton->setChecked(true);

    // 创建输入框
    QLineEdit *searchLineEdit = new QLineEdit();

    // 添加单选按钮和输入框到表单布局
    formLayout->addRow(sampleIdRadioButton);
    formLayout->addRow(sampleNameRadioButton);
    formLayout->addRow(sampleTypeRadioButton);
    formLayout->addRow("请键入对应关键字：", searchLineEdit);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：仅可单选一项。");
    formLayout->addRow(noticeLabel);

    // 连接确认按钮的点击信号
    connect(confirmButton, &QPushButton::clicked, [=]() {
        QString searchKeyword = searchLineEdit->text();
        QString searchColumn;

        for (const QPair<QString, QString>& pair : nameList) {
            if (pair.first == searchGroup->checkedButton()->text().trimmed()) {
                searchColumn = pair.second;
                break;
            }
        }

        if (searchKeyword.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入搜索关键字。");
            return;
        }

        QString sqlQuery;
        QSqlQuery query(fhDatabase);
        sqlQuery = "SELECT * FROM `sample_total` WHERE " + searchColumn + " LIKE ? ORDER BY CAST(SUBSTRING(`sample_id`, 2) AS UNSIGNED) ASC";
        query.prepare(sqlQuery);
        query.addBindValue("%" + searchKeyword + "%"); // 使用通配符进行模糊匹配
        sqlQuery = QString("SELECT * FROM `sample_total` WHERE " + searchColumn + " LIKE %1 ORDER BY CAST(SUBSTRING(`sample_id`, 2) AS UNSIGNED) ASC").arg("%" + searchKeyword + "%");

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << query.executedQuery() << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        qDebug() << sqlQuery;

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

        // 清除原有数据
        if (sample_model) {
            sample_model->clear();
            delete sample_model;
            sample_model = nullptr;
        }

        // 准备model的数据
        sample_model = new QStandardItemModel();

        // 设置表头header
        QStringList headers = getSampleInfoHeaders();
        headers.prepend("选择"); // 在表头前加上一个"选择"列
        sample_model->setHorizontalHeaderLabels(headers);

        // Fill model with data from the database
        int row = 0;
        while (query.next()) {
            // 创建每行的第一列为勾选框
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true); // 设置为可勾选
            checkItem->setCheckState(Qt::Unchecked); // 默认未勾选

            sample_model->setItem(row, 0, checkItem); // 将勾选框设置到第一列

            // Create a new SampleInfo structure for each row
            SampleInfo sample;
            sample.sample_id = query.value("sample_id").toString();
            sample.sample_name = query.value("sample_name").toString();
            sample.sample_type = query.value("sample_type").toString();
            sample.sample_weight = query.value("sample_weight").toDouble();
            sample.sample_dimensions = query.value("sample_dimensions").toString();
            sample.sample_thickness = query.value("sample_thickness").toInt();
            sample.sample_water_content = query.value("sample_water_content").toString();
            sample.sample_service_life = query.value("sample_service_life").toString();
            sample.sample_origin = query.value("sample_origin").toString();
//            sample.sample_image_path = query.value("sample_image_path").toString();
            sample.sample_image_path = dealImagePath(query.value("sample_image_path").toString());

            // struct >> model
            int column = 1; // 从第二列开始
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_id));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_name));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_type));
            sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_weight)));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_dimensions));
            sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_thickness)));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_water_content));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_service_life));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_origin));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_image_path));

            row++;
        }

        // Adjust column size and bind the model to the QTableView
        ui->sample_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->sample_tableView->setModel(sample_model);

        // Resize the table view
        ui->sample_tableView->resize(ui->sample_tableView->width(), ui->sample_tableView->height());
        ui->sample_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(sample_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < sample_model->columnCount(); ++col) {
                    QStandardItem* dataItem = sample_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == sample_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == sample_model->rowCount()";
                } else {
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                }
            }
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        sampleSearchDialog->close();
    });

    // 连接destroyed信号，确保窗口关闭时将sampleSearchDialog置为nullptr
    connect(sampleSearchDialog, &QWidget::destroyed, this, [=]() {
        sampleSearchDialog = nullptr;
    });

    sample_Menu();

    sampleSearchDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    sampleSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    sampleSearchDialog->setFixedSize(500, 190);  // 设置窗口固定大小，宽度足够显示标题
    sampleSearchDialog->setWindowTitle("试样基本信息表总表-基本查询对话框");
    //sampleSearchDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
    //sampleSearchDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    sampleSearchDialog->show();
}

// experiment_total表，基本查询，槽函数
void FHMainWindow::on_syxx_search_btn1_clicked() {
    // 如果对话框已经存在，则不创建新的，直接显示
    if (experimentSearchDialog) {
        experimentSearchDialog->raise();   // 将窗口置于最前
        experimentSearchDialog->activateWindow(); // 激活窗口
        return;
    }

    experimentSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    experimentSearchDialog->setLayout(formLayout);

    QList<QPair<QString, QString>> nameList({
                                                {"按试验编号", "test_id"},
                                                {"按试样编号", "sample_id"},
                                                {"按危险分级", "hazard_level"},
                                                {"按试样材料名称", "sample_name"},
                                                {"按飞火颗粒名称", "fire_particle"},
                                                {"按试验风速", "test_wind_speed"},
                                                {"按引燃状态", "ignition_duration"}
                                            });

    // 创建单选按钮组
    QRadioButton *testIdRadioButton = new QRadioButton(nameList[0].first);
    QRadioButton *sampleIdRadioButton = new QRadioButton(nameList[1].first);
    QRadioButton *particleIdRadioButton = new QRadioButton(nameList[2].first);
    QRadioButton *sampleNameRadioButton = new QRadioButton(nameList[3].first);
    QRadioButton *fireParticleRadioButton = new QRadioButton(nameList[4].first);
    QRadioButton *testWindSpeedRadioButton = new QRadioButton(nameList[5].first);
    QRadioButton *ignitionDurationRadioButton = new QRadioButton(nameList[6].first);

    // 创建状态选择的 QComboBox
    QComboBox *ignitionStatus = new QComboBox();
    ignitionStatus->addItem("");
    ignitionStatus->addItem("未燃");
    ignitionStatus->addItem("阴燃");
    ignitionStatus->addItem("点燃");

    // 设置单选按钮组
    QButtonGroup *searchGroup = new QButtonGroup();
    searchGroup->addButton(testIdRadioButton);
    searchGroup->addButton(sampleIdRadioButton);
    searchGroup->addButton(particleIdRadioButton);
    searchGroup->addButton(sampleNameRadioButton);
    searchGroup->addButton(fireParticleRadioButton);
    searchGroup->addButton(testWindSpeedRadioButton);
    searchGroup->addButton(ignitionDurationRadioButton);
    searchGroup->setExclusive(true); // 确保只有一个按钮被选中
    // 设置第一个按钮为选中状态
    testIdRadioButton->setChecked(true);

    // 创建输入框
    QLineEdit *searchLineEdit = new QLineEdit();


    // 添加单选按钮和输入框到表单布局
    formLayout->addRow(testIdRadioButton);
    formLayout->addRow(sampleIdRadioButton);
    formLayout->addRow(particleIdRadioButton);
    formLayout->addRow(sampleNameRadioButton);
    formLayout->addRow(fireParticleRadioButton);
    formLayout->addRow(testWindSpeedRadioButton);
    formLayout->addRow(ignitionDurationRadioButton, ignitionStatus);
    //formLayout->addRow("请选择引燃状态", ignitionStatus);
    formLayout->addRow("请键入对应关键字：", searchLineEdit);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：仅可单选一项。");
    formLayout->addRow(noticeLabel);

    // 连接确认按钮的点击信号
    connect(confirmButton, &QPushButton::clicked, [=]() {
        QString searchKeyword = searchLineEdit->text();
        QString searchColumn;

        for (const QPair<QString, QString>& pair : nameList) {
            if (pair.first == searchGroup->checkedButton()->text().trimmed()) {
                searchColumn = pair.second;
                break;
            }
        }

        if (searchKeyword.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入搜索关键字。");
            return;
        }

        QString sqlQuery;
        QSqlQuery query(fhDatabase);

        if (searchColumn == "ignition_duration" && ignitionStatus->currentIndex() == 3) {
            QStringList rangeParts = searchKeyword.split('-');
            if (rangeParts.size() != 2) {
                QMessageBox::warning(this, "输入错误", "搜索关键字格式不正确，请使用 '最小值-最大值' 格式。");
                return;
            }

            QString lowerBound = rangeParts[0].trimmed().remove("s"); // 去掉单位
            QString upperBound = rangeParts[1].trimmed().remove("s"); // 去掉单位

            qDebug() << lowerBound << upperBound;

            sqlQuery = "SELECT * FROM `experiment_total` WHERE ignition_duration REGEXP '^[0-9]+s$'AND CAST(SUBSTRING_INDEX(ignition_duration, 's', 1) AS UNSIGNED) BETWEEN ? AND ? ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC";
            query.prepare(sqlQuery);
            query.addBindValue(lowerBound + "s"); // 下限
            query.addBindValue(upperBound + "s"); // 上限
            sqlQuery = QString("SELECT * FROM `experiment_total` WHERE ignition_duration REGEXP '^[0-9]+s$'AND CAST(SUBSTRING_INDEX(ignition_duration, 's', 1) AS UNSIGNED) BETWEEN %1 AND %2 ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC").arg(lowerBound + "s").arg(upperBound + "s");
        } else {
            sqlQuery = "SELECT * FROM `experiment_total` WHERE " + searchColumn + " LIKE ? ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC";
            query.prepare(sqlQuery);
            query.addBindValue("%" + searchKeyword + "%"); // 使用通配符进行模糊匹配
            sqlQuery = QString("SELECT * FROM `experiment_total` WHERE " + searchColumn + " LIKE %1 ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC").arg("%" + searchKeyword + "%");
        }

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << sqlQuery << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        qDebug() << sqlQuery;

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

        // 清除原有数据
        if (experiment_model) {
            experiment_model->clear();
            delete experiment_model;
            experiment_model = nullptr;
        }

        // 准备model的数据
        experiment_model = new QStandardItemModel();

        // 设置表头header
        QStringList headers = getExperimentInfoHeaders();
        headers.prepend("选择"); // 在表头前加上一个"选择"列
        experiment_model->setHorizontalHeaderLabels(headers);

        // Fill model with data from the database
        int row = 0;
        while (query.next()) {
            // 创建每行的第一列为勾选框
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true); // 设置为可勾选
            checkItem->setCheckState(Qt::Unchecked); // 默认未勾选

            experiment_model->setItem(row, 0, checkItem); // 将勾选框设置到第一列

            // Create a new ExperimentInfo structure for each row
            ExperimentInfo experiment;
            experiment.test_id = query.value("test_id").toString();
            experiment.test_time = query.value("test_time").toString();
            experiment.ignition_method = query.value("ignition_method").toString();
            experiment.sample_id = query.value("sample_id").toString();
            experiment.particle_id = query.value("particle_id").toString();
            experiment.sample_name = query.value("sample_name").toString();
            experiment.fire_particle = query.value("fire_particle").toString();
            experiment.particle_count = query.value("particle_count").toInt();
            experiment.test_wind_speed = query.value("test_wind_speed").toString();
            experiment.ignition_duration = query.value("ignition_duration").toString();
            experiment.hazard_level = query.value("hazard_level").toString();
//            experiment.image_path = query.value("image_path").toString();
            experiment.image_path = dealImagePath(query.value("image_path").toString());

            // struct >> model
            int column = 1; // 从第二列开始
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_time));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_method));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.particle_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_name));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.fire_particle));
            experiment_model->setItem(row, column++, new QStandardItem(QString::number(experiment.particle_count)));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_wind_speed));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_duration));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.hazard_level));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.image_path));

            row++;
        }

        // Adjust column size and bind the model to the QTableView
        ui->syxx_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->syxx_tableView->setModel(experiment_model);

        // Resize the table view
        ui->syxx_tableView->resize(ui->syxx_tableView->width(), ui->syxx_tableView->height());
        ui->syxx_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(experiment_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < experiment_model->columnCount(); ++col) {
                    QStandardItem* dataItem = experiment_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == experiment_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == experiment_model->rowCount()";
                } else {
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                }
            }
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        experimentSearchDialog->close();
    });

    // 连接destroyed信号，确保窗口关闭时将fhklSearchDialog置为nullptr
    connect(experimentSearchDialog, &QWidget::destroyed, this, [=]() {
        experimentSearchDialog = nullptr;
    });

    // 连接单选按钮的选中状态变化信号
    connect(testWindSpeedRadioButton, &QRadioButton::toggled, [=](bool checked) {
        if (checked) {
            searchLineEdit->setPlaceholderText("请输入风速v=***m/s，如：2");
        } else {
            searchLineEdit->setPlaceholderText("");  // 清空占位符文本
        }
    });

    // Connect函数，当 ignitionDurationRadioButton 被选中时处理
    connect(ignitionDurationRadioButton, &QRadioButton::toggled, [=](bool checked) {
        if (checked) {
            // 连接 ComboBox 的选择变化
            connect(ignitionStatus, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index) {
                QString statusText = ignitionStatus->currentText();
                if (statusText == "未燃" || statusText == "阴燃" || statusText == "") {
                    searchLineEdit->setText(statusText);  // 直接填充状态文本
                    searchLineEdit->setPlaceholderText("");  // 清空占位符
                } else if (statusText == "点燃") {
                    searchLineEdit->clear();  // 清空已有文本
                    searchLineEdit->setPlaceholderText("请输入引燃时间（s）范围，如：0-100");  // 设置占位符
                }
            });

            // 手动触发一次以更新初始状态
            ignitionStatus->setCurrentIndex(ignitionStatus->currentIndex());
        } else {
            searchLineEdit->clear();  // 清空文本和占位符
            searchLineEdit->setPlaceholderText("");
        }
    });

    experiment_Menu();

    experimentSearchDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    experimentSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    experimentSearchDialog->setFixedSize(500, 290);  // 设置窗口固定大小，宽度足够显示标题
    experimentSearchDialog->setWindowTitle("试验结果及基本信息总表-基本查询对话框");
    //experimentSearchDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
    //experimentSearchDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    experimentSearchDialog->show();
}

// 刷新label的model_count
void FHMainWindow::update_model_count() {
    int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引

    QString labelStyle = "QLabel {"
                         "    font-size: 12pt; "
                         "    font-weight: bold; "
                         "    color: white; "
                         "    background-color: #3498db; "
                         "    border-style: outset; "
                         "    border-width: 2px; "
                         "    border-radius: 10px; "
                         "    border-color: beige; "
                         "    padding: 6px; "
                         "}";

    if (currentIndex == 0) {
        int current_count = fhkl_model->rowCount();

        // 获取QLabel对象
        QLabel *fhkl_search_label = this->findChild<QLabel*>("fhkl_search_label");

        // 确保找到了label
        if (fhkl_search_label) {
            // 设置label的文本为current_count的值
            fhkl_search_label->setText("查询结果统计：共查询到 " + QString::number(current_count) + "条记录。");
            // 应用CSS样式
            fhkl_search_label->setStyleSheet(labelStyle);
        }

    } else if (currentIndex == 1) {
        int current_count = sample_model->rowCount();

        // 获取QLabel对象
        QLabel *sample_search_label = this->findChild<QLabel*>("sample_search_label");

        // 确保找到了label
        if (sample_search_label) {
            // 设置label的文本为current_count的值
            sample_search_label->setText("查询结果统计：共查询到 " + QString::number(current_count) + "条记录。");
            // 应用CSS样式
            sample_search_label->setStyleSheet(labelStyle);
        }

    } else if (currentIndex == 2) {
        int current_count = experiment_model->rowCount();

        // 获取QLabel对象
        QLabel *syxx_search_label = this->findChild<QLabel*>("syxx_search_label");

        // 确保找到了label
        if (syxx_search_label) {
            // 设置label的文本为current_count的值
            syxx_search_label->setText("查询结果统计：共查询到 " + QString::number(current_count) + "条记录。");
            // 应用CSS样式
            syxx_search_label->setStyleSheet(labelStyle);
        }
    }
}

// 刷新label的selected_count
int FHMainWindow::update_selected_count() {
    int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引

    QStandardItemModel *model = nullptr;

    if (currentIndex == 0) {
        model = dynamic_cast<QStandardItemModel*>(ui->fhkl_tableView->model());
    } else if (currentIndex == 1) {
        model = dynamic_cast<QStandardItemModel*>(ui->sample_tableView->model());
    } else if (currentIndex == 2) {
        model = dynamic_cast<QStandardItemModel*>(ui->syxx_tableView->model());
    }

    QLabel *selectedcount_label = this->findChild<QLabel*>("selectedcount_label");

    int current_count = 0;

    for (int row = 0; row < model->rowCount(); ++row) {
        QStandardItem *checkItem = model->item(row, 0);
        if (checkItem && checkItem->checkState() == Qt::Checked) {
            current_count++;
        }
    }

    // 确保找到了label
    if (selectedcount_label) {
        // 设置label的文本为current_count的值
        selectedcount_label->setText("已选 " + QString::number(current_count) + "条记录。");
    }

    return current_count;
}

void FHMainWindow::on_action_logout_triggered()
{
    this->close();
    login *my_login = new login();
    my_login->setWindowTitle("森林-城镇交界域典型建筑材料的引燃和燃烧危险性数据库");
    my_login->show();

}

void FHMainWindow::on_action_exit_triggered()
{
    close();
}

void FHMainWindow::on_fhkltohome_btn_clicked()
{
    database_home *dw = new database_home();
    dw->setValue(true, "fh");
    this->close();
    dw->setWindowTitle("森林-城镇交界域典型建筑材料的引燃和燃烧危险性数据库");
    dw->show();
}

void FHMainWindow::on_sampletohome_btn_clicked()
{
    database_home *dw = new database_home();
    dw->setValue(true, "fh");
    database_home::windowIndex = "fh";
    this->close();
    dw->setWindowTitle("森林-城镇交界域典型建筑材料的引燃和燃烧危险性数据库");
    dw->show();
}

void FHMainWindow::on_syxxtohome_btn_clicked()
{
    database_home *dw = new database_home();
    dw->setValue(true, "fh");
    this->close();
    dw->setWindowTitle("森林-城镇交界域典型建筑材料的引燃和燃烧危险性数据库");
    dw->show();
}

// fhkl_total表，组合查询，槽函数
void FHMainWindow::on_fhkl_search_btn2_clicked() {
    // Similar to the single search, ensure the dialog does not create multiple instances
    if (fhklSearchDialog) {
        fhklSearchDialog->raise();
        fhklSearchDialog->activateWindow();
        return;
    }

    fhklSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    fhklSearchDialog->setLayout(formLayout);

    // Create pairs of radio buttons and line edits
    QList<QPair<QCheckBox*, QLineEdit*>> searchPairs;

    for (const auto &name : {"按飞火颗粒编号", "按飞火颗粒材料名称", "按飞火颗粒材料种类", "按飞火颗粒数目（个）"}) {
        QCheckBox *checkBox = new QCheckBox(name);
        QLineEdit *lineEdit = new QLineEdit();
        lineEdit->setEnabled(false); // Initially disable input
        connect(checkBox, &QCheckBox::toggled, [=](bool checked) {
            lineEdit->setEnabled(checked);
        });

        searchPairs.append(qMakePair(checkBox, lineEdit));
        formLayout->addRow(checkBox, lineEdit);
    }

//    // Create a search button
//    QPushButton *searchButton = new QPushButton("组合查询");
//    formLayout->addRow(searchButton);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：可选择多项，进行组合查询。");
    formLayout->addRow(noticeLabel);

    connect(confirmButton, &QPushButton::clicked, [=]() {
        QStringList conditions;
        for (const auto &pair : searchPairs) {
            QString keyword = pair.second->text();
            if (pair.first->isChecked() && !keyword.isEmpty()) {
                QString columnName = pair.first->text().contains("编号") ? "particle_id" :
                                     pair.first->text().contains("名称") ? "material_name" :
                                     pair.first->text().contains("种类") ? "material_type" :
                                     "particle_count";
                conditions.append(columnName + " LIKE '%" + keyword + "%'");
            }
        }

        if (conditions.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入至少一个搜索关键字。");
            return;
        }

        QString sqlQuery = "SELECT * FROM `fhkl_total` WHERE " + conditions.join(" AND ") + "ORDER BY CAST(SUBSTRING(`particle_id`, 3) AS UNSIGNED) ASC";
        qDebug() << "SQL:" << sqlQuery;
        QSqlQuery query(fhDatabase);
        query.prepare(sqlQuery);

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << sqlQuery << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

        // Clear existing model data
        if (fhkl_model) {
            fhkl_model->clear();
            delete fhkl_model;
            fhkl_model = nullptr;
        }

        // Prepare new model data
        fhkl_model = new QStandardItemModel();
        QStringList headers = getFlyFireParticleHeaders();
        headers.prepend("选择");
        fhkl_model->setHorizontalHeaderLabels(headers);

        int row = 0;
        while (query.next()) {
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true);
            checkItem->setCheckState(Qt::Unchecked);
            fhkl_model->setItem(row, 0, checkItem);

            // Populate model with data
            FlyFireParticle particle;
            particle.particle_id = query.value("particle_id").toString();
            particle.material_name = query.value("material_name").toString();
            particle.material_type = query.value("material_type").toString();
            particle.pre_burn_weight = query.value("pre_burn_weight").toDouble();
            particle.diameter_length = query.value("diameter_length").toString();
            particle.processing_method = query.value("processing_method").toString();
            particle.post_burn_weight = query.value("post_burn_weight").toDouble();
            particle.post_burn_diameter_length = query.value("post_burn_diameter_length").toString();
            particle.particle_count = query.value("particle_count").toInt();
            particle.origin = query.value("origin").toString();
//            particle.image_path = query.value("image_path").toString();
            particle.image_path = dealImagePath(query.value("image_path").toString());

            int column = 1;
            fhkl_model->setItem(row, column++, new QStandardItem(particle.particle_id));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.material_name));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.material_type));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.pre_burn_weight)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.diameter_length));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.processing_method));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.post_burn_weight)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.post_burn_diameter_length));
            fhkl_model->setItem(row, column++, new QStandardItem(QString::number(particle.particle_count)));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.origin));
            fhkl_model->setItem(row, column++, new QStandardItem(particle.image_path));

            row++;
        }

        ui->fhkl_tableView->setModel(fhkl_model);
        ui->fhkl_tableView->resize(ui->fhkl_tableView->width(), ui->fhkl_tableView->height());
        ui->fhkl_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->fhkl_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(fhkl_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < fhkl_model->columnCount(); ++col) {
                    QStandardItem* dataItem = fhkl_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == fhkl_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == fhkl_model->rowCount()";
                } else {
                    //disconnect(ui->selectall_checkBox, &QCheckBox::stateChanged, this, &FHMainWindow::onSelectAllCheckBoxStateChanged);
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                    //connect(ui->selectall_checkBox, &QCheckBox::stateChanged, this, &FHMainWindow::onSelectAllCheckBoxStateChanged);
                }
            }
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        fhklSearchDialog->close();
    });

    connect(fhklSearchDialog, &QWidget::destroyed, this, [=]() {
        fhklSearchDialog = nullptr;
    });

    fhkl_Menu();

    fhklSearchDialog->setAttribute(Qt::WA_DeleteOnClose);
    fhklSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    fhklSearchDialog->setFixedSize(500, 210);
    fhklSearchDialog->setWindowTitle("飞火颗粒基本信息总表-组合查询对话框");

    fhklSearchDialog->show();
}

// sample_total表，组合查询，槽函数
void FHMainWindow::on_sample_search_btn2_clicked() {
    // 如果对话框已经存在，则不创建新的，直接显示
    if (sampleSearchDialog) {
        sampleSearchDialog->raise();   // 将窗口置于最前
        sampleSearchDialog->activateWindow(); // 激活窗口
        return;
    }

    sampleSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    sampleSearchDialog->setLayout(formLayout);

    // Create pairs of radio buttons and line edits
    QList<QPair<QCheckBox*, QLineEdit*>> searchPairs;

    for (const auto &name : {"按试样编号", "按试样材料名称", "按试样材料类型"}) {
        QCheckBox *checkBox = new QCheckBox(name);
        QLineEdit *lineEdit = new QLineEdit();
        lineEdit->setEnabled(false); // Initially disable input
        connect(checkBox, &QCheckBox::toggled, [=](bool checked) {
            lineEdit->setEnabled(checked);
        });

        searchPairs.append(qMakePair(checkBox, lineEdit));
        formLayout->addRow(checkBox, lineEdit);
    }

//    // Create a search button
//    QPushButton *searchButton = new QPushButton("组合查询");
//    formLayout->addRow(searchButton);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：可选择多项，进行组合查询。");
    formLayout->addRow(noticeLabel);

    // 连接确认按钮的点击信号
    connect(confirmButton, &QPushButton::clicked, [=]() {
        QStringList conditions;
        for (const auto &pair : searchPairs) {
            QString keyword = pair.second->text();
            if (pair.first->isChecked() && !keyword.isEmpty()) {
                QString columnName = pair.first->text().contains("编号") ? "sample_id" :
                                     pair.first->text().contains("名称") ? "sample_name" :
                                                                          "sample_type";
                conditions.append(columnName + " LIKE '%" + keyword + "%'");
            }
        }

        if (conditions.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入至少一个搜索关键字。");
            return;
        }

        QString sqlQuery = "SELECT * FROM `sample_total` WHERE " + conditions.join(" AND ") + "ORDER BY CAST(SUBSTRING(`sample_id`, 2) AS UNSIGNED) ASC";
        qDebug() << "SQL:" << sqlQuery;
        QSqlQuery query(fhDatabase);
        query.prepare(sqlQuery);

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << sqlQuery << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

        // 清除原有数据
        if (sample_model) {
            sample_model->clear();
            delete sample_model;
            sample_model = nullptr;
        }

        // 准备model的数据
        sample_model = new QStandardItemModel();

        // 设置表头header
        QStringList headers = getSampleInfoHeaders();
        headers.prepend("选择"); // 在表头前加上一个"选择"列
        sample_model->setHorizontalHeaderLabels(headers);

        // Fill model with data from the database
        int row = 0;
        while (query.next()) {
            // 创建每行的第一列为勾选框
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true); // 设置为可勾选
            checkItem->setCheckState(Qt::Unchecked); // 默认未勾选

            sample_model->setItem(row, 0, checkItem); // 将勾选框设置到第一列

            // Create a new SampleInfo structure for each row
            SampleInfo sample;
            sample.sample_id = query.value("sample_id").toString();
            sample.sample_name = query.value("sample_name").toString();
            sample.sample_type = query.value("sample_type").toString();
            sample.sample_weight = query.value("sample_weight").toDouble();
            sample.sample_dimensions = query.value("sample_dimensions").toString();
            sample.sample_thickness = query.value("sample_thickness").toInt();
            sample.sample_water_content = query.value("sample_water_content").toString();
            sample.sample_service_life = query.value("sample_service_life").toString();
            sample.sample_origin = query.value("sample_origin").toString();
//            sample.sample_image_path = query.value("sample_image_path").toString();
            sample.sample_image_path = dealImagePath(query.value("sample_image_path").toString());

            // struct >> model
            int column = 1; // 从第二列开始
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_id));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_name));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_type));
            sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_weight)));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_dimensions));
            sample_model->setItem(row, column++, new QStandardItem(QString::number(sample.sample_thickness)));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_water_content));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_service_life));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_origin));
            sample_model->setItem(row, column++, new QStandardItem(sample.sample_image_path));

            row++;
        }

        // Adjust column size and bind the model to the QTableView
        ui->sample_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->sample_tableView->setModel(sample_model);

        // Resize the table view
        ui->sample_tableView->resize(ui->sample_tableView->width(), ui->sample_tableView->height());
        ui->sample_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(sample_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < sample_model->columnCount(); ++col) {
                    QStandardItem* dataItem = sample_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == sample_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == sample_model->rowCount()";
                } else {
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                }
            }
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        sampleSearchDialog->close();
    });

    // 连接destroyed信号，确保窗口关闭时将sampleSearchDialog置为nullptr
    connect(sampleSearchDialog, &QWidget::destroyed, this, [=]() {
        sampleSearchDialog = nullptr;
    });

    sample_Menu();

    sampleSearchDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    sampleSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    sampleSearchDialog->setFixedSize(500, 170);  // 设置窗口固定大小，宽度足够显示标题
    sampleSearchDialog->setWindowTitle("试样基本信息表总表-组合查询对话框");
    //sampleSearchDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
    //sampleSearchDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    sampleSearchDialog->show();
}

// experiment_total表，组合查询，槽函数
void FHMainWindow::on_syxx_search_btn2_clicked() {
    // 如果对话框已经存在，则不创建新的，直接显示
    if (experimentSearchDialog) {
        experimentSearchDialog->raise();   // 将窗口置于最前
        experimentSearchDialog->activateWindow(); // 激活窗口
        return;
    }

    experimentSearchDialog = new QWidget(nullptr, Qt::Window);
    QFormLayout *formLayout = new QFormLayout();
    experimentSearchDialog->setLayout(formLayout);

    // 创建状态选择的 QComboBox
    QComboBox *ignitionStatus = new QComboBox();
    ignitionStatus->addItem("");
    ignitionStatus->addItem("未燃");
    ignitionStatus->addItem("阴燃");
    ignitionStatus->addItem("点燃");

    QList<QPair<QCheckBox*, QLineEdit*>> searchPairs;

    QCheckBox *checkBox1 = new QCheckBox("按试验编号");
    QCheckBox *checkBox2 = new QCheckBox("按试样编号");
    QCheckBox *checkBox3 = new QCheckBox("按危险分级");
    QCheckBox *checkBox4 = new QCheckBox("按试样材料名称");
    QCheckBox *checkBox5 = new QCheckBox("按飞火颗粒名称");
    QCheckBox *checkBox6 = new QCheckBox("按试验风速");
    QCheckBox *checkBox7 = new QCheckBox("按引燃状态");


    QLineEdit *lineEdit1 = new QLineEdit();
    QLineEdit *lineEdit2 = new QLineEdit();
    QLineEdit *lineEdit3 = new QLineEdit();
    QLineEdit *lineEdit4 = new QLineEdit();
    QLineEdit *lineEdit5 = new QLineEdit();
    QLineEdit *lineEdit6 = new QLineEdit();
    QLineEdit *lineEdit7 = new QLineEdit();

    lineEdit1->setEnabled(false);
    lineEdit2->setEnabled(false);
    lineEdit3->setEnabled(false);
    lineEdit4->setEnabled(false);
    lineEdit5->setEnabled(false);
    lineEdit6->setEnabled(false);
    lineEdit7->setEnabled(false);

    searchPairs.append(qMakePair(checkBox1, lineEdit1));
    searchPairs.append(qMakePair(checkBox2, lineEdit2));
    searchPairs.append(qMakePair(checkBox3, lineEdit3));
    searchPairs.append(qMakePair(checkBox4, lineEdit4));
    searchPairs.append(qMakePair(checkBox5, lineEdit5));
    searchPairs.append(qMakePair(checkBox6, lineEdit6));
    searchPairs.append(qMakePair(checkBox7, lineEdit7));

    connect(checkBox1, &QCheckBox::toggled, [=](bool checked) {
        lineEdit1->setEnabled(checked);
    });

    connect(checkBox2, &QCheckBox::toggled, [=](bool checked) {
        lineEdit2->setEnabled(checked);
    });

    connect(checkBox3, &QCheckBox::toggled, [=](bool checked) {
        lineEdit3->setEnabled(checked);
    });

    connect(checkBox4, &QCheckBox::toggled, [=](bool checked) {
        lineEdit4->setEnabled(checked);
    });

    connect(checkBox5, &QCheckBox::toggled, [=](bool checked) {
        lineEdit5->setEnabled(checked);
    });

    connect(checkBox6, &QCheckBox::toggled, [=](bool checked) {
        lineEdit6->setEnabled(checked);
    });

    connect(checkBox7, &QCheckBox::toggled, [=](bool checked) {
        lineEdit7->setEnabled(checked);
    });

    formLayout->addRow(checkBox1, lineEdit1);
    formLayout->addRow(checkBox2, lineEdit2);
    formLayout->addRow(checkBox3, lineEdit3);
    formLayout->addRow(checkBox4, lineEdit4);
    formLayout->addRow(checkBox5, lineEdit5);
    formLayout->addRow(checkBox6, lineEdit6);
    formLayout->addRow(checkBox7, ignitionStatus);
    formLayout->addRow(lineEdit7);

//    QPushButton *searchButton = new QPushButton("组合查询");
//    formLayout->addRow(searchButton);

    // 创建确认和取消按钮
    QPushButton *confirmButton = new QPushButton("确认");
    QPushButton *cancelButton = new QPushButton("取消");

    QHBoxLayout *btnLayout = new QHBoxLayout();
    btnLayout->addWidget(confirmButton);
    btnLayout->addWidget(cancelButton);
    formLayout->addRow(btnLayout);

    QLabel *noticeLabel = new QLabel("说明：可选择多项，进行组合查询。");
    formLayout->addRow(noticeLabel);

    // 连接确认按钮的点击信号
    connect(confirmButton, &QPushButton::clicked, [=]() {
        QStringList conditions;
        for (const auto &pair : searchPairs) {
            QString keyword = pair.second->text();
            if (pair.first->isChecked() && !keyword.isEmpty()) {
                QString columnName = pair.first->text().contains("试验编号") ? "test_id" :
                                     pair.first->text().contains("试样编号") ? "sample_id" :
                                     pair.first->text().contains("危险分级") ? "hazard_level" :
                                     pair.first->text().contains("试样材料名称") ? "sample_name" :
                                     pair.first->text().contains("颗粒名称") ? "fire_particle" :
                                     pair.first->text().contains("风速") ? "test_wind_speed" :
                                     "ignition_duration";
                if (columnName != "ignition_duration") {
                    conditions.append(columnName + " LIKE '%" + keyword + "%'");
                }
            }
        }

        if (checkBox7->isChecked() && !lineEdit7->text().isEmpty() && ignitionStatus->currentIndex() != 3) {
            QString columnName = "ignition_duration";
            conditions.append(columnName + " LIKE '%" + lineEdit4->text() + "%'");
        }

        if (conditions.isEmpty()) {
            QMessageBox::warning(this, "警告", "请输入至少一个搜索关键字。");
            return;
        }

        QSqlQuery query(fhDatabase);

        QString sqlQuery = "SELECT * FROM `experiment_total` WHERE " + conditions.join(" AND ") + "ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC";
        query.prepare(sqlQuery);

        if(checkBox7->isChecked() && !lineEdit7->text().isEmpty() && ignitionStatus->currentIndex() == 3) {
            QStringList rangeParts = lineEdit7->text().split('-');
            if (rangeParts.size() != 2) {
                QMessageBox::warning(this, "输入错误", "搜索关键字格式不正确，请使用 '最小值-最大值' 格式。");
                return;
            }

            QString lowerBound = rangeParts[0].trimmed().remove("s"); // 去掉单位
            QString upperBound = rangeParts[1].trimmed().remove("s"); // 去掉单位

            qDebug() << lowerBound << upperBound;

            sqlQuery = "SELECT * FROM `experiment_total` WHERE ignition_duration REGEXP '^[0-9]+s$'AND CAST(SUBSTRING_INDEX(ignition_duration, 's', 1) AS UNSIGNED) BETWEEN ? AND ? AND " + conditions.join(" AND ") + "ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC";
            query.prepare(sqlQuery);
            query.addBindValue(lowerBound + "s"); // 下限
            query.addBindValue(upperBound + "s"); // 上限
            sqlQuery = QString("SELECT * FROM `experiment_total` WHERE ignition_duration REGEXP '^[0-9]+s$'AND CAST(SUBSTRING_INDEX(ignition_duration, 's', 1) AS UNSIGNED) BETWEEN %1 AND %2 AND " + conditions.join(" AND ") + "ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC").arg(lowerBound + "s").arg(upperBound + "s");
        }

        qDebug() << "SQL:" << sqlQuery;

        // 获取当前时间戳（毫秒级精度）
        auto getCurrentTimestamp = []() -> QString {
            return QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss.zzz");
        };

        // 日志文件路径
        QString logFilePath = QDir(QCoreApplication::applicationDirPath()).filePath("mysql_query.log");

        // 记录查询开始时间
        QString startTime = getCurrentTimestamp();
        QElapsedTimer timer;
        timer.start();

        if (!query.exec()) {
            QString endTime = getCurrentTimestamp();
            qWarning() << sqlQuery << " 查询失败: " << query.lastError().text();

            // 记录失败日志
            QFile logFile(logFilePath);
            if (logFile.open(QIODevice::Append | QIODevice::Text)) {
                QTextStream out(&logFile);
                out << QString("[%1] [ERROR] Query failed - %2\n").arg(endTime).arg(query.lastError().text());
                out << QString("  SQL: %1\n").arg(sqlQuery);
                out << QString("  Start: %1, End: %2, Duration: %3 ms\n\n")
                       .arg(startTime).arg(endTime).arg(timer.elapsed());
                logFile.close();
            }
            return;
        }

        // 记录查询结束时间
        QString endTime = getCurrentTimestamp();
        qint64 elapsed = timer.elapsed();

        // 记录成功日志
        QFile logFile(logFilePath);
        if (logFile.open(QIODevice::Append | QIODevice::Text)) {
            QTextStream out(&logFile);
            out << QString("[%1] [INFO] Query executed successfully\n").arg(endTime);
            out << QString("  SQL: %1\n").arg(sqlQuery);
            out << QString("  Start: %1, End: %2, Duration: %3 ms\n").arg(startTime).arg(endTime).arg(elapsed);
            out << QString("  Returned %1 rows\n\n").arg(query.size());
            logFile.close();
        }

        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
        QTimer::singleShot(0, this, [this, elapsed]() {
            QMessageBox::information(
                        this,
                        "查询耗时",
                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
                        );
        });

//        QElapsedTimer timer;
//        timer.start();  // 开始计时

//        if (!query.exec()) {
//            qWarning() << "Failed to search database:" << query.lastError().text();
//            return;
//        }

//        qint64 elapsed = timer.elapsed();  // 获取经过的毫秒数
//        qDebug() << "查询执行时间:" << elapsed << "毫秒";

//        // 延迟 0 毫秒（下一事件循环时显示），确保不阻塞当前函数
//        QTimer::singleShot(0, this, [this, elapsed]() {
//            QMessageBox::information(
//                        this,
//                        "查询耗时",
//                        QString("数据库查询耗时: %1 毫秒").arg(elapsed)
//                        );
//        });

        // 清除原有数据
        if (experiment_model) {
            experiment_model->clear();
            delete experiment_model;
            experiment_model = nullptr;
        }

        // 准备model的数据
        experiment_model = new QStandardItemModel();

        // 设置表头header
        QStringList headers = getExperimentInfoHeaders();
        headers.prepend("选择"); // 在表头前加上一个"选择"列
        experiment_model->setHorizontalHeaderLabels(headers);

        // Fill model with data from the database
        int row = 0;
        while (query.next()) {
            // 创建每行的第一列为勾选框
            QStandardItem *checkItem = new QStandardItem();
            checkItem->setCheckable(true); // 设置为可勾选
            checkItem->setCheckState(Qt::Unchecked); // 默认未勾选

            experiment_model->setItem(row, 0, checkItem); // 将勾选框设置到第一列

            // Create a new ExperimentInfo structure for each row
            ExperimentInfo experiment;
            experiment.test_id = query.value("test_id").toString();
            experiment.test_time = query.value("test_time").toString();
            experiment.ignition_method = query.value("ignition_method").toString();
            experiment.sample_id = query.value("sample_id").toString();
            experiment.particle_id = query.value("particle_id").toString();
            experiment.sample_name = query.value("sample_name").toString();
            experiment.fire_particle = query.value("fire_particle").toString();
            experiment.particle_count = query.value("particle_count").toInt();
            experiment.test_wind_speed = query.value("test_wind_speed").toString();
            experiment.ignition_duration = query.value("ignition_duration").toString();
            experiment.hazard_level = query.value("hazard_level").toString();
//            experiment.image_path = query.value("image_path").toString();
            experiment.image_path = dealImagePath(query.value("image_path").toString());

            // struct >> model
            int column = 1; // 从第二列开始
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_time));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_method));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.particle_id));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.sample_name));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.fire_particle));
            experiment_model->setItem(row, column++, new QStandardItem(QString::number(experiment.particle_count)));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.test_wind_speed));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.ignition_duration));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.hazard_level));
            experiment_model->setItem(row, column++, new QStandardItem(experiment.image_path));

            row++;
        }

        // Adjust column size and bind the model to the QTableView
        ui->syxx_tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
        ui->syxx_tableView->setModel(experiment_model);

        // Resize the table view
        ui->syxx_tableView->resize(ui->syxx_tableView->width(), ui->syxx_tableView->height());
        ui->syxx_tableView->setFont(QFont("SimSun", 10));

        // 捕捉勾选框变化的信号
        connect(experiment_model, &QStandardItemModel::itemChanged, this, [this](QStandardItem *item) {
            if (item->column() == 0) { // 判断是否是勾选框列
                bool isChecked = (item->checkState() == Qt::Checked);
                int row = item->row();
                for (int col = 1; col < experiment_model->columnCount(); ++col) {
                    QStandardItem* dataItem = experiment_model->item(row, col);
                    if (dataItem) {
                        dataItem->setBackground(isChecked ? Qt::yellow : Qt::white); // 勾选时改变整行背景颜色
                    }
                }
                if(update_selected_count() == experiment_model->rowCount()) {
                    ui->selectall_checkBox->setCheckState(Qt::Checked);
                    qDebug() << "update_selected_count() == experiment_model->rowCount()";
                } else {
                    ui->selectall_checkBox->setCheckState(Qt::Unchecked);
                }
            }
        });

        ui->selectall_checkBox->show();

        update_model_count();
    });

    connect(cancelButton, &QPushButton::clicked, [=]() {
        qDebug() << "退出按钮被点击了";
        experimentSearchDialog->close();
    });

    // 连接destroyed信号，确保窗口关闭时将fhklSearchDialog置为nullptr
    connect(experimentSearchDialog, &QWidget::destroyed, this, [=]() {
        experimentSearchDialog = nullptr;
    });

    // 连接单选按钮的选中状态变化信号
    connect(checkBox6, &QCheckBox::toggled, [=](bool checked) {
        if (checked) {
            lineEdit6->setPlaceholderText("请输入风速v=***m/s，如：2");
        } else {
            lineEdit6->setPlaceholderText("");  // 清空占位符文本
        }
    });

    // Connect函数，当 ignitionCheckBox 被选中时处理
    connect(checkBox7, &QCheckBox::toggled, [=](bool checked) {
        if (checked) {
            // 连接 ComboBox 的选择变化
            connect(ignitionStatus, QOverload<int>::of(&QComboBox::currentIndexChanged), [=](int index) {
                QString statusText = ignitionStatus->currentText();
                if (statusText == "未燃" || statusText == "阴燃" || statusText == "") {
                    lineEdit7->setText(statusText);  // 直接填充状态文本
                    lineEdit7->setPlaceholderText("");  // 清空占位符
                } else if (statusText == "点燃") {
                    lineEdit7->clear();  // 清空已有文本
                    lineEdit7->setPlaceholderText("请输入引燃时间（s）范围，如：0-100");  // 设置占位符
                }
            });

            // 手动触发一次以更新初始状态
            ignitionStatus->setCurrentIndex(ignitionStatus->currentIndex());
        } else {
            lineEdit7->clear();  // 清空文本和占位符
            lineEdit7->setPlaceholderText("");
        }
    });

    experiment_Menu();

    experimentSearchDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
    experimentSearchDialog->setWindowIcon(QIcon(":/images/fire.png"));
    experimentSearchDialog->setFixedSize(500, 320);  // 设置窗口固定大小，宽度足够显示标题
    experimentSearchDialog->setWindowTitle("试验结果及基本信息总表-组合查询对话框");
    //experimentSearchDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
    //experimentSearchDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
    experimentSearchDialog->show();
}

// 导出所选行
void FHMainWindow::on_exportselected_btn_clicked() {

    int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引

    QStandardItemModel *model = nullptr;

    if (currentIndex == 0) {
        model = dynamic_cast<QStandardItemModel*>(ui->fhkl_tableView->model());
    } else if (currentIndex == 1) {
        model = dynamic_cast<QStandardItemModel*>(ui->sample_tableView->model());
    } else if (currentIndex == 2) {
        model = dynamic_cast<QStandardItemModel*>(ui->syxx_tableView->model());
    }

    if (!model || model->rowCount() == 0) {
        QMessageBox::warning(this, "错误", "当前选项卡没有有效的数据模型。");
        return;
    }

    if(model->headerData(0, Qt::Horizontal).toString() != "选择") {
        QMessageBox::warning(this, "警告", "未勾选任何行");
        return;
    }

    // Open a file dialog to choose the file location
    bool anyRowChecked = false;
    QString fileName = QFileDialog::getSaveFileName(this, "保存为 CSV", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), "CSV Files (*.csv);;All Files (*)");
    if (fileName.isEmpty()) {
        return; // User canceled the dialog
    }

    // Ensure the file name ends with .csv
    if (!fileName.endsWith(".csv", Qt::CaseInsensitive)) {
        fileName += ".csv";
    }

    {
        QFile file(fileName);
        if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QMessageBox::warning(this, "错误", "无法打开文件以写入数据。");
            return;
        }

        QTextStream out(&file);

        out.setCodec("GBK"); // 使用 GBK 编码

        // Write the header
        QStringList headers;
        for (int column = 1; column < model->columnCount(); ++column) {
            headers << model->headerData(column, Qt::Horizontal).toString();
        }
        out << headers.join(",") << "\n";

        // Write the data
        for (int row = 0; row < model->rowCount(); ++row) {
            QStandardItem *checkItem = model->item(row, 0);
            if (checkItem && checkItem->checkState() == Qt::Checked) {
                anyRowChecked = true;
                QStringList rowData;
                for (int column = 1; column < model->columnCount(); ++column) { // Start from column 1 to skip the checkbox
                    QString itemData = model->data(model->index(row, column)).toString();
                    rowData << itemData;
                }
                out << rowData.join(",") << "\n";
            }
        }

    } // 文件在这里自动关闭

    if (!anyRowChecked) {
        QMessageBox::warning(this, "错误", "没有选中任何行。");
        QFile::remove(fileName);
        qDebug() << "delete empty .csv filename: " << fileName;
        return;
    }

    QFileInfo fileInfo(fileName);
    QString baseName = fileInfo.completeBaseName(); // 获取不包含扩展名的文件名
    QMessageBox::information(this, "成功", "数据已成功导出为 CSV 文件：" + baseName + ".csv。");
}

// 导出整表
void FHMainWindow::on_exportall_btn_clicked() {

    int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引
    QStringList headers;
    QSqlQuery query(fhDatabase);

    if (currentIndex == 0) {
        headers = getFlyFireParticleHeaders();
        query.prepare("SELECT `particle_id`, `material_name`, `material_type`, `pre_burn_weight`,`diameter_length`, `processing_method`, `post_burn_weight`,`post_burn_diameter_length`, `particle_count`, `origin`, `image_path` FROM `fhkl_total` ORDER BY CAST(SUBSTRING(`particle_id`, 3) AS UNSIGNED) ASC");
    } else if (currentIndex == 1) {
        headers =getSampleInfoHeaders();
        query.prepare("SELECT `sample_id`, `sample_name`, `sample_type`, `sample_weight`,`sample_dimensions`, `sample_thickness`, `sample_water_content`,`sample_service_life`, `sample_origin`, `sample_image_path` FROM `sample_total` ORDER BY CAST(SUBSTRING(`sample_id`, 2) AS UNSIGNED) ASC");
    } else if (currentIndex == 2) {
        headers = getExperimentInfoHeaders();
        query.prepare("SELECT `test_id`, `test_time`, `ignition_method`, `sample_id`,`particle_id`, `sample_name`, `fire_particle`, `particle_count`,`test_wind_speed`, `ignition_duration`, `hazard_level`, `image_path` FROM `experiment_total` ORDER BY CAST(SUBSTRING(`test_id`, 2) AS UNSIGNED) ASC");
    }

    if (!query.exec()) {
        QMessageBox::warning(this, "错误", "查询数据库失败: " + query.lastError().text());
        return;
    }

    // Open a file dialog to choose the file location
    QString fileName = QFileDialog::getSaveFileName(this, "保存为 CSV", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation), "CSV Files (*.csv);;All Files (*)");
    if (fileName.isEmpty()) {
        return; // User canceled the dialog
    }

    // Ensure the file name ends with .csv
    if (!fileName.endsWith(".csv", Qt::CaseInsensitive)) {
        fileName += ".csv";
    }

    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        QMessageBox::warning(this, "错误", "无法打开文件以写入数据。");
        return;
    }

    QTextStream out(&file);

    out.setCodec("GBK"); // 使用 GBK 编码

    out << headers.join(",") << "\n";

    // Write the data, skipping excluded columns
    while (query.next()) {
        QStringList rowData;
        for (int i = 0; i < query.record().count(); ++i) {
            QString item = query.value(i).toString();
            // Wrap items in quotes if they contain commas
            if (item.contains(",")) {
                item = "\"" + item + "\"";
            }
            rowData << item;
        }
        out << rowData.join(",") << "\n";
    }

    file.close();

    QFileInfo fileInfo(fileName);
    QString baseName = fileInfo.completeBaseName(); // 获取不包含扩展名的文件名
    QMessageBox::information(this, "成功", "数据已成功导出为 CSV 文件：" + baseName + ".csv。");
}

// fhkl表，鼠标右键菜单
void FHMainWindow::fhkl_Menu() {
    connect(ui->fhkl_tableView, &QTableView::customContextMenuRequested, [=](const QPoint &pos) {
        QModelIndex index = ui->fhkl_tableView->indexAt(pos);
        if (index.isValid()) {
            // 创建右键菜单
            QMenu menu(ui->fhkl_tableView);

            // 添加菜单项
            QAction *editAction;
            QAction *removeAction;
            QAction *saveAction;
            QAction *deleteAction;
            QAction *showPicAction;

            // 权限检测
            if (login::userType != "User") {
                editAction = menu.addAction("编辑");
                removeAction = menu.addAction("移除");
                menu.addSeparator();
                saveAction = menu.addAction("保存该行到数据库");
                deleteAction = menu.addAction("从数据库中删除该行");
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
            } else if(login::userType == "User") {
                editAction = nullptr;
                removeAction = menu.addAction("移除");
                saveAction = nullptr;
                deleteAction = nullptr;
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
            }

            // 连接菜单项的点击信号
            connect(editAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->fhkl_tableView->selectionModel()->currentIndex();
                QString old_key = fhkl_model->item(selectedIndex.row(), 1)->text();
                if (selectedIndex.isValid()) {
                    // Check if the checkbox in the first column is checked
                    QStandardItem *checkItem = fhkl_model->item(selectedIndex.row(), 0);
                    if (checkItem && checkItem->checkState() == Qt::Checked) {
                        // 这里可以执行编辑操作
                        qDebug() << "编辑操作：行" << selectedIndex.row() << "列" << selectedIndex.column();

                        // Create a line edit for editing
                        QLineEdit *lineEdit = new QLineEdit();
                        lineEdit->setText(fhkl_model->item(selectedIndex.row(), selectedIndex.column())->text());

                        // Create a dialog for editing
                        QDialog editDialog(this);
                        QVBoxLayout *layout = new QVBoxLayout(&editDialog);
                        layout->addWidget(lineEdit);

                        QPushButton *saveButton = new QPushButton("暂存");
                        layout->addWidget(saveButton);

                        // Connect the save button
                        connect(saveButton, &QPushButton::clicked, [&]() {
                            // Update the model with the new value
                            fhkl_model->item(selectedIndex.row(), selectedIndex.column())->setText(lineEdit->text());
                            fhkl_model->item(selectedIndex.row(), selectedIndex.column())->setBackground(Qt::green);
                            editDialog.accept(); // Close the dialog
                        });

                        editDialog.setWindowTitle("编辑");
                        editDialog.exec(); // Show dialog modally
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(removeAction, &QAction::triggered, [=]() {
                // 执行移除操作
                QModelIndex selectedIndex = ui->fhkl_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行移除操作
                    qDebug() << "移除操作：行" << selectedIndex.row();
                    QStandardItem* selectedItem = fhkl_model->item(selectedIndex.row(), 0);
                    if (selectedItem->checkState() == Qt::Checked) {
                        fhkl_model->takeRow(selectedIndex.row());
                        ui->fhkl_tableView->setModel(fhkl_model);
                        update_selected_count();
                        update_model_count();
                    }
                }
            });

            connect(saveAction , &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->fhkl_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行保存操作
                    qDebug() << "保存操作：行" << selectedIndex.row();
                    QStandardItem* selectedItem = fhkl_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        // Extract values from the selected row
                        QString particleId = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 1)).toString();
                        QString materialName = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 2)).toString();
                        QString materialType = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 3)).toString();
                        double preBurnWeight = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 4)).toDouble();
                        QString diameterLength = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 5)).toString();
                        QString processingMethod = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 6)).toString();
                        double postBurnWeight = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 7)).toDouble();
                        QString postBurnDiameterLength = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 8)).toString();
                        int particleCount = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 9)).toInt();
                        QString origin = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 10)).toString();
                        QString imagePath = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 11)).toString();

                        // Prepare the SQL update statement
                        QSqlQuery query(fhDatabase);
                        query.prepare("UPDATE `fhkl_total` SET "
                                      "`material_name` = ?, "
                                      "`material_type` = ?, "
                                      "`pre_burn_weight` = ?, "
                                      "`diameter_length` = ?, "
                                      "`processing_method` = ?, "
                                      "`post_burn_weight` = ?, "
                                      "`post_burn_diameter_length` = ?, "
                                      "`particle_count` = ?, "
                                      "`origin` = ?, "
                                      "`image_path` = ?, "
                                      "`updated_time` = NOW() "
                                      "WHERE `particle_id` = ?");

                        // Bind the values to the query
                        query.addBindValue(materialName);
                        query.addBindValue(materialType);
                        query.addBindValue(preBurnWeight);
                        query.addBindValue(diameterLength);
                        query.addBindValue(processingMethod);
                        query.addBindValue(postBurnWeight);
                        query.addBindValue(postBurnDiameterLength);
                        query.addBindValue(particleCount);
                        query.addBindValue(origin);
                        query.addBindValue(imagePath);
                        query.addBindValue(particleId); // Assuming particle_id is the unique identifier

                        // Execute the query
                        if (!query.exec()) {
                            QMessageBox::warning(this, "错误", "更新数据库失败: " + query.lastError().text());
                        } else {
                            QMessageBox::information(this, "成功", "数据已成功更新。");
                        }
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(deleteAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->fhkl_tableView->selectionModel()->currentIndex();
                 if (selectedIndex.isValid()) {
                     // 这里可以删除保存操作
                     qDebug() << "保存删除：行" << selectedIndex.row();
                     QStandardItem* selectedItem = fhkl_model->item(selectedIndex.row(), 0);
                     if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                         QString particleId = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 1)).toString();
                         QSqlQuery query(fhDatabase);

                         // Prepare the DELETE SQL statement
                         query.prepare("DELETE FROM `fhkl_total` WHERE `particle_id` = ?");
                         query.addBindValue(particleId);

                         if (!query.exec()) {
                             QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                         } else {
                             // Successfully deleted, remove the row from the model
                             fhkl_model->removeRow(selectedIndex.row());
                             QMessageBox::information(this, "成功", "数据已成功删除。");
                             update_model_count();
                             update_selected_count();
                         }
                     } else {
                         QMessageBox::warning(this, "警告", "请先选择该行的勾选框以进行删除。");
                     }
                 }
            });

            connect(showPicAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->fhkl_tableView->selectionModel()->currentIndex();
                 if (selectedIndex.isValid()) {
                     // 这里可以show操作
                     qDebug() << "show picture：行" << selectedIndex.row();
                     QStandardItem* selectedItem = fhkl_model->item(selectedIndex.row(), 0);
                     if (selectedItem && selectedItem->checkState() == Qt::Checked) {

                         QString particleId = fhkl_model->data(fhkl_model->index(selectedIndex.row(), 1)).toString();
                         QSqlQuery query(fhDatabase);
                         query.prepare("SELECT * FROM `fhkl_total` WHERE `particle_id` = ?");
                         query.addBindValue(particleId);
                         if (!query.exec()) {
                             qWarning() << "Failed to search database:" << query.lastError().text();
                             return;
                         }
                         query.next();

                         QString image_path = query.value("image_path").toString();

                         image_path = image_path.startsWith("..") ? globalFHDirPath + image_path.mid(QString("..").length()) : image_path;
                         //QString image_path = fhkl_model->data(fhkl_model->index(selectedIndex.row(), fhkl_model->columnCount() - 1)).toString();

                         qDebug() << image_path;
                         QFileInfo fileInfo(image_path);
                         if (!fileInfo.exists()) {
                             qWarning() << "文件不存在:" << image_path;
                             QMessageBox::warning(this, "警告", "文件不存在:" + image_path);
                             //return;
                         }
                         // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
                         QUrl fileUrl = QUrl::fromLocalFile(image_path);//应当放出来，fhkl表提供了假地址，代码暂时无效
                         //QUrl fileUrl = QUrl::fromLocalFile("F:\\CUIT\\xfsjk\\试验V3\\实验台图片\\实验台.jpg");
                         qDebug() << fileUrl;
                         // 使用 QDesktopServices::openUrl 来打开文件
                         if (!QDesktopServices::openUrl(fileUrl)) {
                             qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
                         }
                     } else {
                         QMessageBox::warning(this, "警告", "请先选择该行的勾选框以获得图片地址进行展示。");
                     }
                 }
            });

            // 显示菜单
            menu.exec(ui->fhkl_tableView->mapToGlobal(pos));
        }
    });
}

// sample表，鼠标右键菜单
void FHMainWindow::sample_Menu() {
    connect(ui->sample_tableView, &QTableView::customContextMenuRequested, [=](const QPoint &pos) {
        QModelIndex index = ui->sample_tableView->indexAt(pos);
        if (index.isValid()) {
            // 创建右键菜单
            QMenu menu(ui->sample_tableView);

            // 添加菜单项
            QAction *editAction;
            QAction *removeAction;
            QAction *saveAction;
            QAction *deleteAction;
            QAction *showPicAction;

            // 权限检测
            if (login::userType != "User") {
                editAction = menu.addAction("编辑");
                removeAction = menu.addAction("移除");
                menu.addSeparator();
                saveAction = menu.addAction("保存该行到数据库");
                deleteAction = menu.addAction("从数据库中删除该行");
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
            } else if(login::userType == "User") {
                editAction = nullptr;
                removeAction = menu.addAction("移除");
                saveAction = nullptr;
                deleteAction = nullptr;
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
            }

            // 连接菜单项的点击信号
            connect(editAction, &QAction::triggered, [=]() {
                // 执行编辑操作，例如选择行进行编辑
                QModelIndex selectedIndex = ui->sample_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // Check if the checkbox in the first column is checked
                    QStandardItem *checkItem = sample_model->item(selectedIndex.row(), 0);
                    if (checkItem && checkItem->checkState() == Qt::Checked) {
                        // 这里可以执行编辑操作
                        qDebug() << "编辑操作：行" << selectedIndex.row() << "列" << selectedIndex.column();

                        // Create a line edit for editing
                        QLineEdit *lineEdit = new QLineEdit();
                        lineEdit->setText(sample_model->item(selectedIndex.row(), selectedIndex.column())->text());

                        // Create a dialog for editing
                        QDialog editDialog(this);
                        QVBoxLayout *layout = new QVBoxLayout(&editDialog);
                        layout->addWidget(lineEdit);

                        QPushButton *saveButton = new QPushButton("暂存");
                        layout->addWidget(saveButton);

                        // Connect the save button
                        connect(saveButton, &QPushButton::clicked, [&]() {
                            // Update the model with the new value
                            sample_model->item(selectedIndex.row(), selectedIndex.column())->setText(lineEdit->text());
                            sample_model->item(selectedIndex.row(), selectedIndex.column())->setBackground(Qt::green);
                            editDialog.accept(); // Close the dialog
                        });

                        editDialog.setWindowTitle("编辑");
                        editDialog.exec(); // Show dialog modally
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(removeAction, &QAction::triggered, [=]() {
                // 执行移除操作
                QModelIndex selectedIndex = ui->sample_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行移除操作
                    qDebug() << "移除操作：行" << selectedIndex.row() << "列" << selectedIndex.column();
                    QStandardItem* selectedItem = sample_model->item(selectedIndex.row(), 0);
                    if (selectedItem->checkState() == Qt::Checked) {
                        sample_model->takeRow(selectedIndex.row());
                        ui->sample_tableView->setModel(sample_model);
                        update_selected_count();
                        update_model_count();
                    }
                }
            });

            connect(saveAction , &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->sample_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行保存操作
                    qDebug() << "保存操作：行" << selectedIndex.row();
                    QStandardItem* selectedItem = sample_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        // Extract values from the selected row
                        QString sampleId = sample_model->data(sample_model->index(selectedIndex.row(), 1)).toString();
                        QString sampleName = sample_model->data(sample_model->index(selectedIndex.row(), 2)).toString();
                        QString sampleType = sample_model->data(sample_model->index(selectedIndex.row(), 3)).toString();
                        double sampleWeight = sample_model->data(sample_model->index(selectedIndex.row(), 4)).toDouble();
                        QString sampleDimensions = sample_model->data(sample_model->index(selectedIndex.row(), 5)).toString();
                        int sampleThickness = sample_model->data(sample_model->index(selectedIndex.row(), 6)).toInt();
                        QString sampleWaterContent = sample_model->data(sample_model->index(selectedIndex.row(), 7)).toString();
                        QString sampleServiceLife = sample_model->data(sample_model->index(selectedIndex.row(), 8)).toString();
                        QString sampleOrigin = sample_model->data(sample_model->index(selectedIndex.row(), 9)).toString();
                        QString sampleImagePath = sample_model->data(sample_model->index(selectedIndex.row(), 10)).toString();
                        // Prepare the SQL update statement
                        QSqlQuery query(fhDatabase);
                        query.prepare("UPDATE `sample_total` SET "
                                      "`sample_name` = ?, "
                                      "`sample_type` = ?, "
                                      "`sample_weight` = ?, "
                                      "`sample_dimensions` = ?, "
                                      "`sample_thickness` = ?, "
                                      "`sample_water_content` = ?, "
                                      "`sample_service_life` = ?, "
                                      "`sample_origin` = ?, "
                                      "`sample_image_path` = ?, "
                                      "`updated_time` = NOW() "
                                      "WHERE `sample_id` = ?");

                        // Bind the values to the query
                        query.addBindValue(sampleName);
                        query.addBindValue(sampleType);
                        query.addBindValue(sampleWeight);
                        query.addBindValue(sampleDimensions);
                        query.addBindValue(sampleThickness);
                        query.addBindValue(sampleWaterContent);
                        query.addBindValue(sampleServiceLife);
                        query.addBindValue(sampleOrigin);
                        query.addBindValue(sampleImagePath);
                        query.addBindValue(sampleId); // Assuming sample_id is the unique identifier
                        // Execute the query
                        if (!query.exec()) {
                            QMessageBox::warning(this, "错误", "更新数据库失败: " + query.lastError().text());
                        } else {
                            QMessageBox::information(this, "成功", "数据已成功更新。");
                        }
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(deleteAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->sample_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以删除保存操作
                    qDebug() << "保存删除：行" << selectedIndex.row();
                    QStandardItem* selectedItem = sample_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        QString sampleId = sample_model->data(sample_model->index(selectedIndex.row(), 1)).toString();
                        QSqlQuery query(fhDatabase);

                        // Prepare the DELETE SQL statement
                        query.prepare("DELETE FROM `sample_total` WHERE `sample_id` = ?");
                        query.addBindValue(sampleId);

                        if (!query.exec()) {
                            QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                        } else {
                            // Successfully deleted, remove the row from the model
                            sample_model->removeRow(selectedIndex.row());
                            QMessageBox::information(this, "成功", "数据已成功删除。");
                            update_model_count();
                            update_selected_count();
                        }
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框以进行删除。");
                    }
                }
            });

            connect(showPicAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->sample_tableView->selectionModel()->currentIndex();
                 if (selectedIndex.isValid()) {
                     // 这里可以show操作
                     qDebug() << "show picture：行" << selectedIndex.row();
                     QStandardItem* selectedItem = sample_model->item(selectedIndex.row(), 0);
                     if (selectedItem && selectedItem->checkState() == Qt::Checked) {

                         QString sampleId = sample_model->data(sample_model->index(selectedIndex.row(), 1)).toString();
                         QSqlQuery query(fhDatabase);
                         query.prepare("SELECT * FROM `sample_total` WHERE `sample_id` = ?");
                         query.addBindValue(sampleId);
                         if (!query.exec()) {
                             qWarning() << "Failed to search database:" << query.lastError().text();
                             return;
                         }
                         query.next();

                         QString image_path = query.value("sample_image_path").toString();

                         image_path = image_path.startsWith("..") ? globalFHDirPath + image_path.mid(QString("..").length()) : image_path;
                         //QString image_path = sample_model->data(sample_model->index(selectedIndex.row(), sample_model->columnCount() - 1)).toString();

                         qDebug() << image_path;
                         QFileInfo fileInfo(image_path);
                         if (!fileInfo.exists()) {
                             qWarning() << "文件不存在:" << image_path;
                             QMessageBox::warning(this, "警告", "文件不存在:" + image_path);
                             //return;
                         }
                         // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
                         QUrl fileUrl = QUrl::fromLocalFile(image_path);

                         qDebug() << fileUrl;
                         // 使用 QDesktopServices::openUrl 来打开文件
                         if (!QDesktopServices::openUrl(fileUrl)) {
                             qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
                         }
                     } else {
                         QMessageBox::warning(this, "警告", "请先选择该行的勾选框以获得图片地址进行展示。");
                     }
                 }
            });

            // 显示菜单
            menu.exec(ui->sample_tableView->mapToGlobal(pos));
        }
    });
}

// experiment表，鼠标右键菜单
void FHMainWindow::experiment_Menu() {
    connect(ui->syxx_tableView, &QTableView::customContextMenuRequested, [=](const QPoint &pos) {
        QModelIndex index = ui->syxx_tableView->indexAt(pos);
        if (index.isValid()) {
            // 创建右键菜单
            QMenu menu(ui->syxx_tableView);

            // 添加菜单项
            QAction *editAction;
            QAction *removeAction;
            QAction *saveAction;
            QAction *deleteAction;
            QAction *showPicAction;
            QAction *showFhklAction;
            QAction *showSampleAction;

            // 权限检测
            if (login::userType != "User") {
                editAction = menu.addAction("编辑");
                removeAction = menu.addAction("移除");
                menu.addSeparator();
                saveAction = menu.addAction("保存该行到数据库");
                deleteAction = menu.addAction("从数据库中删除该行");
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
                showFhklAction = menu.addAction("展示该行飞火颗粒详情");
                showSampleAction = menu.addAction("展示该行试样详情");
            } else if(login::userType == "User") {
                editAction = nullptr;
                removeAction = menu.addAction("移除");
                saveAction = nullptr;
                deleteAction = nullptr;
                menu.addSeparator();
                showPicAction = menu.addAction("展示该行指向的图片");
                showFhklAction = menu.addAction("展示该行飞火颗粒详情");
                showSampleAction = menu.addAction("展示该行试样详情");
            }

            // 连接菜单项的点击信号
            connect(editAction, &QAction::triggered, [=]() {
                // 执行编辑操作，例如选择行进行编辑
                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // Check if the checkbox in the first column is checked
                    QStandardItem *checkItem = experiment_model->item(selectedIndex.row(), 0);
                    if (checkItem && checkItem->checkState() == Qt::Checked) {
                        // 这里可以执行编辑操作
                        qDebug() << "编辑操作：行" << selectedIndex.row() << "列" << selectedIndex.column();

                        // Create a line edit for editing
                        QLineEdit *lineEdit = new QLineEdit();
                        lineEdit->setText(experiment_model->item(selectedIndex.row(), selectedIndex.column())->text());

                        // Create a dialog for editing
                        QDialog editDialog(this);
                        QVBoxLayout *layout = new QVBoxLayout(&editDialog);
                        layout->addWidget(lineEdit);

                        QPushButton *saveButton = new QPushButton("暂存");
                        layout->addWidget(saveButton);

                        // Connect the save button
                        connect(saveButton, &QPushButton::clicked, [&]() {
                            // Update the model with the new value
                            experiment_model->item(selectedIndex.row(), selectedIndex.column())->setText(lineEdit->text());
                            experiment_model->item(selectedIndex.row(), selectedIndex.column())->setBackground(Qt::green);
                            editDialog.accept(); // Close the dialog
                        });

                        editDialog.setWindowTitle("编辑");
                        editDialog.exec(); // Show dialog modally
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(removeAction, &QAction::triggered, [=]() {
                // 执行移除操作
                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行移除操作
                    qDebug() << "移除操作：行" << selectedIndex.row() << "列" << selectedIndex.column();
                    QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                    if (selectedItem->checkState() == Qt::Checked) {
                        experiment_model->takeRow(selectedIndex.row());
                        ui->syxx_tableView->setModel(experiment_model);
                        update_selected_count();
                        update_model_count();
                    }
                }
            });

            connect(saveAction , &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以执行保存操作
                    qDebug() << "保存操作：行" << selectedIndex.row();
                    QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        // Extract values from the selected row
                        QString testId = experiment_model->data(experiment_model->index(selectedIndex.row(), 1)).toString();
                        QString testTime = experiment_model->data(experiment_model->index(selectedIndex.row(), 2)).toString();
                        QString ignitionMethod = experiment_model->data(experiment_model->index(selectedIndex.row(), 3)).toString();
                        QString sampleId = experiment_model->data(experiment_model->index(selectedIndex.row(), 4)).toString();
                        QString particleId = experiment_model->data(experiment_model->index(selectedIndex.row(), 5)).toString();
                        QString sampleName = experiment_model->data(experiment_model->index(selectedIndex.row(), 6)).toString();
                        QString fireParticle = experiment_model->data(experiment_model->index(selectedIndex.row(), 7)).toString();
                        int particleCount = experiment_model->data(experiment_model->index(selectedIndex.row(), 8)).toInt();
                        QString testWindSpeed = experiment_model->data(experiment_model->index(selectedIndex.row(), 9)).toString();
                        QString ignitionDuration = experiment_model->data(experiment_model->index(selectedIndex.row(), 10)).toString();
                        QString hazardLevel = experiment_model->data(experiment_model->index(selectedIndex.row(), 11)).toString();
                        QString imagePath = experiment_model->data(experiment_model->index(selectedIndex.row(), 12)).toString();

                        // Prepare the SQL update statement
                        QSqlQuery query(fhDatabase);
                        query.prepare("UPDATE `experiment_total` SET "
                                      "`test_time` = ?, "
                                      "`ignition_method` = ?, "
                                      "`sample_id` = ?, "
                                      "`particle_id` = ?, "
                                      "`sample_name` = ?, "
                                      "`fire_particle` = ?, "
                                      "`particle_count` = ?, "
                                      "`test_wind_speed` = ?, "
                                      "`ignition_duration` = ?, "
                                      "`hazard_level` = ?, "
                                      "`image_path` = ?, "
                                      "`updated_time` = NOW() "
                                      "WHERE `test_id` = ?");

                        // Bind the values to the query
                        query.addBindValue(testTime);
                        query.addBindValue(ignitionMethod);
                        query.addBindValue(sampleId);
                        query.addBindValue(particleId);
                        query.addBindValue(sampleName);
                        query.addBindValue(fireParticle);
                        query.addBindValue(particleCount);
                        query.addBindValue(testWindSpeed);
                        query.addBindValue(ignitionDuration);
                        query.addBindValue(hazardLevel);
                        query.addBindValue(imagePath);
                        query.addBindValue(testId); // Assuming test_id is the unique identifier

                        // Execute the query
                        if (!query.exec()) {
                            QMessageBox::warning(this, "错误", "更新数据库失败: " + query.lastError().text());
                        } else {
                            QMessageBox::information(this, "成功", "数据已成功更新。");
                        }
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框进行编辑。");
                    }
                }
            });

            connect(deleteAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                if (selectedIndex.isValid()) {
                    // 这里可以删除保存操作
                    qDebug() << "保存删除：行" << selectedIndex.row();
                    QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        QString testId = experiment_model->data(experiment_model->index(selectedIndex.row(), 1)).toString();
                        QSqlQuery query(fhDatabase);

                        // Prepare the DELETE SQL statement
                        query.prepare("DELETE FROM `experiment_total` WHERE `test_id` = ?");
                        query.addBindValue(testId);

                        if (!query.exec()) {
                            QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                        } else {
                            // Successfully deleted, remove the row from the model
                            experiment_model->removeRow(selectedIndex.row());
                            QMessageBox::information(this, "成功", "数据已成功删除。");
                            update_model_count();
                            update_selected_count();
                        }
                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框以进行删除。");
                    }
                }
            });

            connect(showPicAction, &QAction::triggered, [=]() {
                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                 if (selectedIndex.isValid()) {
                     // 这里可以show操作
                     qDebug() << "show picture：行" << selectedIndex.row();
                     QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                     if (selectedItem && selectedItem->checkState() == Qt::Checked) {

                         QString testId = experiment_model->data(experiment_model->index(selectedIndex.row(), 1)).toString();
                         QSqlQuery query(fhDatabase);
                         query.prepare("SELECT * FROM `experiment_total` WHERE `test_id` = ?");
                         query.addBindValue(testId);
                         if (!query.exec()) {
                             qWarning() << "Failed to search database:" << query.lastError().text();
                             return;
                         }
                         query.next();

                         QString image_path = query.value("image_path").toString();

                         image_path = image_path.startsWith("..") ? globalFHDirPath + image_path.mid(QString("..").length()) : image_path;

                         //QString image_path = experiment_model->data(experiment_model->index(selectedIndex.row(), experiment_model->columnCount() - 1)).toString();

                         qDebug() << image_path;
                         QFileInfo fileInfo(image_path);
                         if (!fileInfo.exists()) {
                             qWarning() << "文件不存在:" << image_path;
                             QMessageBox::warning(this, "警告", "文件不存在:" + image_path);
                             //return;
                         }
                         // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
                         QUrl fileUrl = QUrl::fromLocalFile(image_path);

                         qDebug() << fileUrl;
                         // 使用 QDesktopServices::openUrl 来打开文件
                         if (!QDesktopServices::openUrl(fileUrl)) {
                             qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
                         }
                     } else {
                         QMessageBox::warning(this, "警告", "请先选择该行的勾选框以获得图片地址进行展示。");
                     }
                 }
            });

            connect(showFhklAction, &QAction::triggered, [=]() {

                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                QString particle_id_selected;
                QString fhkl_image_path;
                if (selectedIndex.isValid()) {
                    // 这里可以show操作
                    qDebug() << "show fhkl_line：行" << selectedIndex.row();
                    QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        particle_id_selected = experiment_model->data(experiment_model->index(selectedIndex.row(), 5)).toString();
                        qDebug() << "particle_id_selected: " << particle_id_selected;

                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框以获得飞火颗粒信息进行展示。");
                        return;
                    }
                }

//                if (showFhklDialog) {
//                    showFhklDialog->raise();
//                    showFhklDialog->activateWindow();
//                    return;
//                }

                if (showFhklDialog) {
                    showFhklDialog->close();
                }

                showFhklDialog = new QWidget(nullptr, Qt::Window);
                QFormLayout *formLayout = new QFormLayout();
                showFhklDialog->setLayout(formLayout);

                // Create pairs of radio buttons and line edits
                QList<QPair<QLabel*, QLineEdit*>> showPairs;

                for (const auto &name : getFlyFireParticleHeaders()) {
                    QLabel *fhklLabel = new QLabel(name);
                    QLineEdit *lineEdit = new QLineEdit();
                    lineEdit->setEnabled(false); // Initially disable input
                    //                    connect(checkBox, &QCheckBox::toggled, [=](bool checked) {
                    //                        lineEdit->setEnabled(checked);
                    //                    });

                    showPairs.append(qMakePair(fhklLabel, lineEdit));
                    formLayout->addRow(fhklLabel, lineEdit);
                }

                // 创建确认和取消按钮
                QPushButton *showPicButton = new QPushButton("展示图片");

                QHBoxLayout *btnLayout = new QHBoxLayout();
                btnLayout->addWidget(showPicButton);
                formLayout->addRow(btnLayout);


                // 检查数据库连接是否有效
                if (!(fhDatabase).isOpen()) {
                    qWarning() << "数据库连接不可用。";
                    return;
                }

                QSqlQuery query(fhDatabase);

                // 检查 particle_id 是否已存在
                query.prepare("SELECT * FROM `fhkl_total` WHERE `particle_id` = ?");
                query.addBindValue(particle_id_selected);

                if (!query.exec()) {
                    qDebug() << "Failed to execute query:" << query.lastError().text();
                    return;
                }

                // 判断结果集，如果记录数大于 0 则存在
                if (query.next()) {
                    FlyFireParticle particle;
                    particle.particle_id = query.value("particle_id").toString();
                    particle.material_name = query.value("material_name").toString();
                    particle.material_type = query.value("material_type").toString();
                    particle.pre_burn_weight = query.value("pre_burn_weight").toDouble();
                    particle.diameter_length = query.value("diameter_length").toString();
                    particle.processing_method = query.value("processing_method").toString();
                    particle.post_burn_weight = query.value("post_burn_weight").toDouble();
                    particle.post_burn_diameter_length = query.value("post_burn_diameter_length").toString();
                    particle.particle_count = query.value("particle_count").toInt();
                    particle.origin = query.value("origin").toString();
                    fhkl_image_path = query.value("image_path").toString();
                    particle.image_path = dealImagePath(fhkl_image_path);
                    fhkl_image_path = fhkl_image_path.startsWith("..") ? globalFHDirPath + fhkl_image_path.mid(QString("..").length()) : fhkl_image_path;

                    // struct >> lineEdit
                    showPairs.at(0).second->setText(particle.particle_id);
                    showPairs.at(1).second->setText(particle.material_name);
                    showPairs.at(2).second->setText(particle.material_type);
                    showPairs.at(3).second->setText(QString::number(particle.pre_burn_weight));
                    showPairs.at(4).second->setText(particle.diameter_length);
                    showPairs.at(5).second->setText(particle.processing_method);
                    showPairs.at(6).second->setText(QString::number(particle.post_burn_weight));
                    showPairs.at(7).second->setText(particle.post_burn_diameter_length);
                    showPairs.at(8).second->setText(QString::number(particle.particle_count));
                    showPairs.at(9).second->setText(particle.origin);
                    showPairs.at(10).second->setText(particle.image_path);

                } else {
                    QMessageBox::warning(this, "警告", "不存在(" + particle_id_selected + ")对应的飞火颗粒详细信息。");
                    return;
                }

                // lambda 表达式的捕获列表中添加对 image_path_selected 的捕获
                connect(showPicButton, &QPushButton::clicked, this, [fhkl_image_path , this](){                    
                    QFileInfo fileInfo(fhkl_image_path);
                    if (!fileInfo.exists()) {
                        qWarning() << "文件不存在:" << fhkl_image_path;
                        QMessageBox::warning(this, "警告", "文件不存在:" + fhkl_image_path);
                        //return;
                    }
                    // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
                    QUrl fileUrl = QUrl::fromLocalFile(fhkl_image_path);

                    qDebug() << fileUrl;
                    // 使用 QDesktopServices::openUrl 来打开文件
                    if (!QDesktopServices::openUrl(fileUrl)) {
                        qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
                    }
                });

                connect(showFhklDialog, &QWidget::destroyed, this, [=]() {
                    showFhklDialog = nullptr;
                });

                //showFhklDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
                showFhklDialog->setWindowIcon(QIcon(":/images/fire.png"));
                //showFhklDialog->setFixedSize(500, 440);  // 设置窗口固定大小，宽度足够显示标题
                showFhklDialog->setMinimumSize(550, 440); // 设置最小大小，确保窗口不会太小
                showFhklDialog->setWindowTitle(particle_id_selected + "-飞火颗粒信息详情对话框");
                //showFhklDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
                //showFhklDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
                showFhklDialog->setStyleSheet("QWidget { font-size: 12pt; }");
                showFhklDialog->show();

            });

            connect(showSampleAction, &QAction::triggered, [=]() {

                QModelIndex selectedIndex = ui->syxx_tableView->selectionModel()->currentIndex();
                QString sample_id_selected;
                QString sample_image_path;
                if (selectedIndex.isValid()) {
                    // 这里可以show操作
                    qDebug() << "show sample_line：行" << selectedIndex.row();
                    QStandardItem* selectedItem = experiment_model->item(selectedIndex.row(), 0);
                    if (selectedItem && selectedItem->checkState() == Qt::Checked) {
                        sample_id_selected = experiment_model->data(experiment_model->index(selectedIndex.row(), 4)).toString();
                        qDebug() << "sample_id_selected: " << sample_id_selected;

                    } else {
                        QMessageBox::warning(this, "警告", "请先选择该行的勾选框以获得试样信息进行展示。");
                        return;
                    }
                }

//                if (showSampleDialog) {
//                    showSampleDialog->raise();
//                    showSampleDialog->activateWindow();
//                    return;
//                }

                if (showSampleDialog) {
                    showSampleDialog->close();
                }

                showSampleDialog = new QWidget(nullptr, Qt::Window);
                QFormLayout *formLayout = new QFormLayout();
                showSampleDialog->setLayout(formLayout);

                // Create pairs of radio buttons and line edits
                QList<QPair<QLabel*, QLineEdit*>> showPairs;

                for (const auto &name : getSampleInfoHeaders()) {
                    QLabel *sampleLabel = new QLabel(name);
                    QLineEdit *lineEdit = new QLineEdit();
                    lineEdit->setEnabled(false); // Initially disable input
                    //                    connect(checkBox, &QCheckBox::toggled, [=](bool checked) {
                    //                        lineEdit->setEnabled(checked);
                    //                    });

                    showPairs.append(qMakePair(sampleLabel, lineEdit));
                    formLayout->addRow(sampleLabel, lineEdit);
                }

                // 创建确认和取消按钮
                QPushButton *showPicButton = new QPushButton("展示图片");

                QHBoxLayout *btnLayout = new QHBoxLayout();
                btnLayout->addWidget(showPicButton);
                formLayout->addRow(btnLayout);


                // 检查数据库连接是否有效
                if (!(fhDatabase).isOpen()) {
                    qWarning() << "数据库连接不可用。";
                    return;
                }

                QSqlQuery query(fhDatabase);

                // 检查 particle_id 是否已存在
                query.prepare("SELECT * FROM `sample_total` WHERE `sample_id` = ?");
                query.addBindValue(sample_id_selected);

                if (!query.exec()) {
                    qDebug() << "Failed to execute query:" << query.lastError().text();
                    return;
                }

                // 判断结果集，如果记录数大于 0 则存在
                if (query.next()) {
                    SampleInfo sample;
                    sample.sample_id = query.value("sample_id").toString();
                    sample.sample_name = query.value("sample_name").toString();
                    sample.sample_type = query.value("sample_type").toString();
                    sample.sample_weight = query.value("sample_weight").toDouble();
                    sample.sample_dimensions = query.value("sample_dimensions").toString();
                    sample.sample_thickness = query.value("sample_thickness").toInt();
                    sample.sample_water_content = query.value("sample_water_content").toString();
                    sample.sample_service_life = query.value("sample_service_life").toString();
                    sample.sample_origin = query.value("sample_origin").toString();
                    sample_image_path = query.value("sample_image_path").toString();
                    sample.sample_image_path = dealImagePath(sample_image_path);
                    sample_image_path = sample_image_path.startsWith("..") ? globalFHDirPath + sample_image_path.mid(QString("..").length()) : sample_image_path;

                    // struct >> lineEdit
                    showPairs.at(0).second->setText(sample.sample_id);
                    showPairs.at(1).second->setText(sample.sample_name);
                    showPairs.at(2).second->setText(sample.sample_type);
                    showPairs.at(3).second->setText(QString::number(sample.sample_weight));
                    showPairs.at(4).second->setText(sample.sample_dimensions);
                    showPairs.at(5).second->setText(QString::number(sample.sample_thickness));
                    showPairs.at(6).second->setText(sample.sample_water_content);
                    showPairs.at(7).second->setText(sample.sample_service_life);
                    showPairs.at(8).second->setText(sample.sample_origin);
                    showPairs.at(9).second->setText(sample.sample_image_path);

                } else {
                    QMessageBox::warning(this, "警告", "不存在(" + sample_id_selected + ")对应的试样详细信息。");
                    return;
                }

                // lambda 表达式的捕获列表中添加对 image_path_selected 的捕获
                connect(showPicButton, &QPushButton::clicked, this, [sample_image_path , this](){
                    QFileInfo fileInfo(sample_image_path);
                    if (!fileInfo.exists()) {
                        qWarning() << "文件不存在:" << sample_image_path;
                        QMessageBox::warning(this, "警告", "文件不存在:" + sample_image_path);
                        //return;
                    }
                    // 使用 QUrl::fromLocalFile 来创建一个 URL 对象
                    QUrl fileUrl = QUrl::fromLocalFile(sample_image_path);

                    qDebug() << fileUrl;
                    // 使用 QDesktopServices::openUrl 来打开文件
                    if (!QDesktopServices::openUrl(fileUrl)) {
                        qWarning() << "文件URL打开失败:" << fileUrl << "请检查！";
                    }
                });

                connect(showSampleDialog, &QWidget::destroyed, this, [=]() {
                    showSampleDialog = nullptr;
                });

                //showSampleDialog->setAttribute(Qt::WA_DeleteOnClose); // 设置自动删除属性
                showSampleDialog->setWindowIcon(QIcon(":/images/fire.png"));
                //showSampleDialog->setFixedSize(500, 440);  // 设置窗口固定大小，宽度足够显示标题
                showSampleDialog->setMinimumSize(550, 440); // 设置最小大小，确保窗口不会太小
                showSampleDialog->setWindowTitle(sample_id_selected + "-试样信息详情对话框");
                //showSampleDialog->setWindowModality(Qt::WindowModal); // 如果你希望它是模态对话框
                //showSampleDialog->setWindowModality(Qt::ApplicationModal); // 设置为模态对话框（可选）
                showSampleDialog->setStyleSheet("QWidget { font-size: 12pt; }");
                showSampleDialog->show();
            });

            // 显示菜单
            menu.exec(ui->syxx_tableView->mapToGlobal(pos));
        }
    });
}

// 数据修改，提示操作
void FHMainWindow::on_action_update_triggered()
{
    QMessageBox::information(this ,"操作提示-数据修改" ,"1、基本查询或组合查询后，勾选目标行；\n"
                                               "2、鼠标指针移动到当前勾选行的目标列，点击鼠标右键，再点击菜单中的“编辑”按钮；\n"
                                               "3、弹出鼠标指针所在单元框的文本编辑框，可键入新数据；\n"
                                               "4、点击文本编辑框的“暂存”按钮，该单元框背景会置为绿色，表示已有改动操作；\n"
                                               "5、再次点击鼠标右键，点击“保存该行到数据库”按钮，即可完成数据修改操作。");
}

// 数据删除，操作提示
void FHMainWindow::on_action_delete_triggered()
{
    QMessageBox::information(this ,"操作提示-数据删除" ,"1、基本查询或组合查询后，勾选目标行；\n"
                                               "2、鼠标指针移动到当前勾选行，点击鼠标右键，再点击菜单中的“从数据库中删除该行”按钮；\n"
                                               "3、等待数据库执行成功，即可完成数据删除操作。");
}

// 根据用户组，选择显示相对还是绝对路径
QString FHMainWindow::dealImagePath(const QString &filePath) {
//    if(login::userType != "User") {
//        return filePath;
//    }

    QFileInfo fileInfo(filePath);
//    QString baseName = fileInfo.completeBaseName(); // 获取不包含扩展名的文件名
//    qDebug() << "!!!去除扩展名后的文件名为：" << baseName;

    QString directoryPath = fileInfo.dir().absolutePath(); // 获取包含文件名的完整路径

//    qDebug() << "!!!测试路径为：" << directoryPath; // 去除文件名的文件夹绝对路径

    // 去掉文件名，保留目录路径
    directoryPath = directoryPath.left(directoryPath.lastIndexOf("/"));
    // 确保目录路径以正斜杠结束
    if (!directoryPath.endsWith("/")) {
        directoryPath += "/";
    }
//    qDebug() << "!!!保留路径为：" << directoryPath; // 需要将这一部分替换成 "..\\"

    directoryPath = directoryPath.replace("/" , "\\");

    // 确认 directoryPath 在这里已经被正确赋值
//    qDebug() << "!!!替换后的路径为：" << directoryPath;

    // 使用替换后的 directoryPath 替换 filePath 中的路径部分
    QString tempString = filePath;
    tempString = tempString.replace(directoryPath, "..\\");

//    qDebug() << "!!!处理后用于显示的相对路径：" << tempString;

    return tempString;
}

// 移除所选行，槽函数
void FHMainWindow::on_deleteselected_btn_clicked()
{
    int currentIndex = ui->fhtabWidget->currentIndex();  // 获取当前选项卡的索引
    qDebug() << "Current Tab Index:" << currentIndex;

    // 添加确认对话框
    QMessageBox::StandardButton reply;
    reply = QMessageBox::warning(this, "确认删除", "您确定要删除所选的记录吗？",
                                 QMessageBox::Yes | QMessageBox::No);
    if (reply == QMessageBox::No) {
        return; // 如果用户点击了“否”，则不执行删除操作
    }

    QSqlQuery query(fhDatabase);

    if (currentIndex == 0) {
        // 对第一个选项卡 (fhkl) 执行删除操作
        if(fhkl_model->headerData(0, Qt::Horizontal).toString() != "选择") {
            QMessageBox::warning(this, "警告", "未勾选任何行");
            return;
        }
        qDebug() << "fhkl_model->rowCount():" << fhkl_model->rowCount();
        for (int row = fhkl_model->rowCount() - 1; row >= 0; --row) {  // 从后往前删除
            QStandardItem* selectedItem = fhkl_model->item(row, 0);
            QString particleId = fhkl_model->data(fhkl_model->index(row, 1)).toString();
            if (selectedItem->checkState() == Qt::Checked) {
                qDebug() << "Deleting row:" << row;
                fhkl_model->takeRow(row);  // 删除行

                query.prepare("DELETE FROM `fhkl_total` WHERE `particle_id` = ?");
                query.addBindValue(particleId);
                if (!query.exec()) {
                    QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                }
            }
        }
        ui->fhkl_tableView->setModel(fhkl_model);  // 刷新视图

    } else if (currentIndex == 1) {
        // 对第二个选项卡 (sample) 执行删除操作
        if(sample_model->headerData(0, Qt::Horizontal).toString() != "选择") {
            QMessageBox::warning(this, "警告", "未勾选任何行");
            return;
        }
        qDebug() << "sample_model->rowCount():" << sample_model->rowCount();
        for (int row = sample_model->rowCount() - 1; row >= 0; --row) {  // 从后往前删除
            QStandardItem* selectedItem = sample_model->item(row, 0);
            QString sampleId = sample_model->data(sample_model->index(row, 1)).toString();
            if (selectedItem->checkState() == Qt::Checked) {
                qDebug() << "Deleting row:" << row;
                sample_model->takeRow(row);  // 删除行

                query.prepare("DELETE FROM `sample_total` WHERE `sample_id` = ?");
                query.addBindValue(sampleId);
                if (!query.exec()) {
                    QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                }
            }
        }
        ui->sample_tableView->setModel(sample_model);  // 刷新视图

    } else if (currentIndex == 2) {
        // 对第三个选项卡 (syxx) 执行删除操作
        if(experiment_model->headerData(0, Qt::Horizontal).toString() != "选择") {
            QMessageBox::warning(this, "警告", "未勾选任何行");
            return;
        }
        qDebug() << "experiment_model->rowCount():" <<  experiment_model->rowCount();
        for (int row = experiment_model->rowCount() - 1; row >= 0; --row) {  // 从后往前删除
            QStandardItem* selectedItem = experiment_model->item(row, 0);
            QString testId = experiment_model->data(experiment_model->index(row, 1)).toString();
            if (selectedItem->checkState() == Qt::Checked) {
                qDebug() << "Deleting row:" << row;
                experiment_model->takeRow(row);  // 删除行

                query.prepare("DELETE FROM `experiment_total` WHERE `test_id` = ?");
                query.addBindValue(testId);
                if (!query.exec()) {
                    QMessageBox::warning(this, "错误", "删除数据失败: " + query.lastError().text());
                }
            }
        }
        ui->syxx_tableView->setModel(experiment_model);  // 刷新视图
    }
    update_model_count();
    update_selected_count();
}

void FHMainWindow::on_action_dirpath_triggered()
{
    // 创建一个弹窗
    QDialog dialog(this);
    dialog.setWindowTitle(tr("设置目标文件夹路径"));
    dialog.resize(400, 150);

    // 创建布局和控件
    QVBoxLayout *layout = new QVBoxLayout(&dialog);

    QLabel *label = new QLabel(tr("当前文件夹路径："));
    QLineEdit *lineEdit = new QLineEdit();
    QPushButton *browseButton = new QPushButton(tr("选择文件夹"));
    QPushButton *saveButton = new QPushButton(tr("保存路径"));
    QHBoxLayout *buttonLayout = new QHBoxLayout();

    buttonLayout->addWidget(browseButton);
    buttonLayout->addWidget(saveButton);

    // 将控件添加到布局
    layout->addWidget(label);
    layout->addWidget(lineEdit);
    layout->addLayout(buttonLayout);

    // 读取 ini 文件中的路径并设置到文本框
    QSettings setting(CONFIGPATH, QSettings::IniFormat);
    setting.setIniCodec(QTextCodec::codecForName("UTF-8"));
    QString iniDirPath = setting.value("fhsettings/fhdirpath").toString();
    lineEdit->setText(iniDirPath);

    // 浏览按钮的逻辑
    connect(browseButton, &QPushButton::clicked, [&]() {
        QString dirPath = QFileDialog::getExistingDirectory(
                    &dialog, tr("选择目标文件夹路径"), iniDirPath,
                    QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);

        if (!dirPath.isEmpty()) {
            lineEdit->setText(dirPath); // 更新文本框内容
        }
    });

    // 保存按钮的逻辑
    connect(saveButton, &QPushButton::clicked, [&]() {
        QString updatedDirPath = lineEdit->text();

        if (updatedDirPath.isEmpty()) {
            QMessageBox::warning(&dialog, tr("警告"), tr("文件夹路径不能为空！"));
            return;
        }

        // 将路径保存到全局变量和 ini 文件
        globalFHDirPath = updatedDirPath;
        setting.setValue("fhsettings/fhdirpath", globalFHDirPath);

        QMessageBox::information(&dialog, tr("保存成功"), tr("文件夹路径已成功保存到配置文件！"));
        dialog.accept(); // 关闭弹窗
    });

    // 显示弹窗
    dialog.exec();
}
